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:
117
internal/endtoend/CLAUDE.md
Normal file
117
internal/endtoend/CLAUDE.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# End-to-End Tests - Native Database Setup
|
||||
|
||||
This document describes how to set up MySQL and PostgreSQL for running end-to-end tests in environments without Docker, particularly when using an HTTP proxy.
|
||||
|
||||
## Overview
|
||||
|
||||
The end-to-end tests support three methods for connecting to databases:
|
||||
|
||||
1. **Environment Variables**: Set `POSTGRESQL_SERVER_URI` and `MYSQL_SERVER_URI` directly
|
||||
2. **Docker**: Automatically starts containers via the docker package
|
||||
3. **Native Installation**: Starts existing database services on Linux
|
||||
|
||||
## Installing Databases with HTTP Proxy
|
||||
|
||||
In environments where DNS doesn't work directly but an HTTP proxy is available (e.g., some CI environments), you need to configure apt to use the proxy before installing packages.
|
||||
|
||||
### Configure apt Proxy
|
||||
|
||||
```bash
|
||||
# Check if HTTP_PROXY is set
|
||||
echo $HTTP_PROXY
|
||||
|
||||
# Configure apt to use the proxy
|
||||
sudo tee /etc/apt/apt.conf.d/99proxy << EOF
|
||||
Acquire::http::Proxy "$HTTP_PROXY";
|
||||
Acquire::https::Proxy "$HTTPS_PROXY";
|
||||
EOF
|
||||
|
||||
# Update package lists
|
||||
sudo apt-get update -qq
|
||||
```
|
||||
|
||||
### Install PostgreSQL
|
||||
|
||||
```bash
|
||||
# Install PostgreSQL
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql postgresql-contrib
|
||||
|
||||
# Start the service
|
||||
sudo service postgresql start
|
||||
|
||||
# Set password for postgres user
|
||||
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';"
|
||||
|
||||
# Configure pg_hba.conf for password authentication
|
||||
# Find the hba_file location:
|
||||
sudo -u postgres psql -t -c "SHOW hba_file;"
|
||||
|
||||
# Add md5 authentication for localhost (add to the beginning of pg_hba.conf):
|
||||
# host all all 127.0.0.1/32 md5
|
||||
|
||||
# Reload PostgreSQL
|
||||
sudo service postgresql reload
|
||||
```
|
||||
|
||||
### Install MySQL
|
||||
|
||||
```bash
|
||||
# Pre-configure MySQL root password
|
||||
echo "mysql-server mysql-server/root_password password mysecretpassword" | sudo debconf-set-selections
|
||||
echo "mysql-server mysql-server/root_password_again password mysecretpassword" | sudo debconf-set-selections
|
||||
|
||||
# Install MySQL
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y mysql-server
|
||||
|
||||
# Start the service
|
||||
sudo service mysql start
|
||||
|
||||
# Verify connection
|
||||
mysql -uroot -pmysecretpassword -e "SELECT 1;"
|
||||
```
|
||||
|
||||
## Expected Database Credentials
|
||||
|
||||
The native database support expects the following credentials:
|
||||
|
||||
### PostgreSQL
|
||||
- **URI**: `postgres://postgres:postgres@localhost:5432/postgres?sslmode=disable`
|
||||
- **User**: `postgres`
|
||||
- **Password**: `postgres`
|
||||
- **Port**: `5432`
|
||||
|
||||
### MySQL
|
||||
- **URI**: `root:mysecretpassword@tcp(localhost:3306)/mysql?multiStatements=true&parseTime=true`
|
||||
- **User**: `root`
|
||||
- **Password**: `mysecretpassword`
|
||||
- **Port**: `3306`
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run end-to-end tests
|
||||
go test -v -run TestReplay -timeout 20m ./internal/endtoend/...
|
||||
|
||||
# With verbose logging
|
||||
go test -v -run TestReplay -timeout 20m ./internal/endtoend/... 2>&1 | tee test.log
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### apt-get times out or fails
|
||||
- Ensure HTTP proxy is configured in `/etc/apt/apt.conf.d/99proxy`
|
||||
- Check that the proxy URL is correct: `echo $HTTP_PROXY`
|
||||
- Try running `sudo apt-get update` first to verify connectivity
|
||||
|
||||
### MySQL connection refused
|
||||
- Check if MySQL is running: `sudo service mysql status`
|
||||
- Verify the password: `mysql -uroot -pmysecretpassword -e "SELECT 1;"`
|
||||
- Check if MySQL is listening on TCP: `netstat -tlnp | grep 3306`
|
||||
|
||||
### PostgreSQL authentication failed
|
||||
- Verify pg_hba.conf has md5 authentication for localhost
|
||||
- Check password: `PGPASSWORD=postgres psql -h localhost -U postgres -c "SELECT 1;"`
|
||||
- Reload PostgreSQL after config changes: `sudo service postgresql reload`
|
||||
|
||||
### DNS resolution fails
|
||||
This is expected in some environments. Configure apt proxy as shown above.
|
||||
143
internal/endtoend/case_test.go
Normal file
143
internal/endtoend/case_test.go
Normal file
@@ -0,0 +1,143 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type Testcase struct {
|
||||
Name string
|
||||
Path string
|
||||
ConfigName string
|
||||
Stderr []byte
|
||||
Stdout []byte
|
||||
Exec *Exec
|
||||
}
|
||||
|
||||
type ExecMeta struct {
|
||||
InvalidSchema bool `json:"invalid_schema"`
|
||||
}
|
||||
|
||||
type Exec struct {
|
||||
Command string `json:"command"`
|
||||
Args []string `json:"args"`
|
||||
Contexts []string `json:"contexts"`
|
||||
Process string `json:"process"`
|
||||
OS []string `json:"os"`
|
||||
Env map[string]string `json:"env"`
|
||||
Meta ExecMeta `json:"meta"`
|
||||
}
|
||||
|
||||
func parseStderr(t *testing.T, dir, testctx string) []byte {
|
||||
t.Helper()
|
||||
paths := []string{
|
||||
filepath.Join(dir, "stderr", fmt.Sprintf("%s.txt", testctx)),
|
||||
filepath.Join(dir, fmt.Sprintf("stderr_%s.txt", runtime.GOOS)),
|
||||
filepath.Join(dir, "stderr.txt"),
|
||||
}
|
||||
for _, path := range paths {
|
||||
if _, err := os.Stat(path); !os.IsNotExist(err) {
|
||||
blob, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return blob
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// parseStdout reads the command's expected output: stdout.json for a
|
||||
// command that prints JSON, so editors highlight it, otherwise stdout.txt.
|
||||
func parseStdout(t *testing.T, dir string) []byte {
|
||||
t.Helper()
|
||||
for _, name := range []string{"stdout.json", "stdout.txt"} {
|
||||
path := filepath.Join(dir, name)
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
blob, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return blob
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// hasSQLCConfig reports whether dir contains an sqlc configuration file.
|
||||
func hasSQLCConfig(dir string) bool {
|
||||
for _, name := range []string{"sqlc.json", "sqlc.yaml", "sqlc.yml"} {
|
||||
if _, err := os.Stat(filepath.Join(dir, name)); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func parseExec(t *testing.T, dir string) *Exec {
|
||||
t.Helper()
|
||||
path := filepath.Join(dir, "exec.json")
|
||||
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
var e Exec
|
||||
blob, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %s", path, err)
|
||||
}
|
||||
if err := json.Unmarshal(blob, &e); err != nil {
|
||||
t.Fatalf("%s: %s", path, err)
|
||||
}
|
||||
if e.Command == "" {
|
||||
e.Command = "generate"
|
||||
}
|
||||
return &e
|
||||
}
|
||||
|
||||
func FindTests(t *testing.T, root, testctx string) []*Testcase {
|
||||
var tcs []*Testcase
|
||||
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := info.Name()
|
||||
if name == "sqlc.json" || name == "sqlc.yaml" || name == "sqlc.yml" {
|
||||
dir := filepath.Dir(path)
|
||||
tcs = append(tcs, &Testcase{
|
||||
Path: dir,
|
||||
Name: strings.TrimPrefix(dir, root+string(filepath.Separator)),
|
||||
ConfigName: name,
|
||||
Stderr: parseStderr(t, dir, testctx),
|
||||
Stdout: parseStdout(t, dir),
|
||||
Exec: parseExec(t, dir),
|
||||
})
|
||||
return filepath.SkipDir
|
||||
}
|
||||
// Config-less command tests (e.g. parse, analyze) are discovered by
|
||||
// their exec.json when no sqlc config is present in the directory.
|
||||
if name == "exec.json" {
|
||||
dir := filepath.Dir(path)
|
||||
if !hasSQLCConfig(dir) {
|
||||
tcs = append(tcs, &Testcase{
|
||||
Path: dir,
|
||||
Name: strings.TrimPrefix(dir, root+string(filepath.Separator)),
|
||||
Stderr: parseStderr(t, dir, testctx),
|
||||
Stdout: parseStdout(t, dir),
|
||||
Exec: parseExec(t, dir),
|
||||
})
|
||||
return filepath.SkipDir
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return tcs
|
||||
}
|
||||
64
internal/endtoend/ddl_test.go
Normal file
64
internal/endtoend/ddl_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/config"
|
||||
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
|
||||
)
|
||||
|
||||
func TestValidSchema(t *testing.T) {
|
||||
for _, replay := range FindTests(t, "testdata", "base") {
|
||||
|
||||
if replay.Exec != nil {
|
||||
if replay.Exec.Meta.InvalidSchema {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Config-less command tests (parse, analyze) have no schema to validate.
|
||||
if replay.ConfigName == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
file := filepath.Join(replay.Path, replay.ConfigName)
|
||||
rd, err := os.Open(file)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
conf, err := config.ParseConfig(rd)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for j, pkg := range conf.SQL {
|
||||
switch pkg.Engine {
|
||||
case config.EnginePostgreSQL:
|
||||
// pass
|
||||
case config.EngineMySQL:
|
||||
// pass
|
||||
default:
|
||||
continue
|
||||
}
|
||||
t.Run(fmt.Sprintf("endtoend-%s-%d", file, j), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var schema []string
|
||||
for _, path := range pkg.Schema {
|
||||
schema = append(schema, filepath.Join(filepath.Dir(file), path))
|
||||
}
|
||||
|
||||
switch pkg.Engine {
|
||||
case config.EnginePostgreSQL:
|
||||
local.PostgreSQL(t, schema)
|
||||
case config.EngineMySQL:
|
||||
local.MySQL(t, schema)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
456
internal/endtoend/endtoend_test.go
Normal file
456
internal/endtoend/endtoend_test.go
Normal file
@@ -0,0 +1,456 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
osexec "os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/cmd"
|
||||
"github.com/sqlc-dev/sqlc/internal/config"
|
||||
"github.com/sqlc-dev/sqlc/internal/opts"
|
||||
"github.com/sqlc-dev/sqlc/internal/sqlcdebug"
|
||||
"github.com/sqlc-dev/sqlc/internal/sqltest/docker"
|
||||
"github.com/sqlc-dev/sqlc/internal/sqltest/native"
|
||||
)
|
||||
|
||||
// withSQLCDEBUG installs the given SQLCDEBUG-formatted string for the
|
||||
// duration of the test and restores the empty default afterwards.
|
||||
//
|
||||
// Callers in TestReplay are sequential, so this does not need a mutex:
|
||||
// Go's test scheduler does not run TestReplay concurrently with the
|
||||
// parallel top-level tests in this package.
|
||||
func withSQLCDEBUG(t *testing.T, raw string) func() {
|
||||
t.Helper()
|
||||
if raw == "" {
|
||||
return func() {}
|
||||
}
|
||||
sqlcdebug.Update(raw)
|
||||
return func() { sqlcdebug.Update("") }
|
||||
}
|
||||
|
||||
func lineEndings() cmp.Option {
|
||||
return cmp.Transformer("LineEndings", func(in string) string {
|
||||
// Replace Windows new lines with Unix newlines
|
||||
return strings.Replace(in, "\r\n", "\n", -1)
|
||||
})
|
||||
}
|
||||
|
||||
func stderrTransformer() cmp.Option {
|
||||
return cmp.Transformer("Stderr", func(in string) string {
|
||||
s := strings.Replace(in, "\r", "", -1)
|
||||
return strings.Replace(s, "\\", "/", -1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestExamples(t *testing.T) {
|
||||
t.Parallel()
|
||||
ctx := context.Background()
|
||||
|
||||
examples, err := filepath.Abs(filepath.Join("..", "..", "examples"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
files, err := os.ReadDir(examples)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, replay := range files {
|
||||
if !replay.IsDir() {
|
||||
continue
|
||||
}
|
||||
tc := replay.Name()
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
path := filepath.Join(examples, tc)
|
||||
var stderr bytes.Buffer
|
||||
opts := &cmd.Options{
|
||||
Env: cmd.Env{},
|
||||
Stderr: &stderr,
|
||||
}
|
||||
output, err := cmd.Generate(ctx, path, "", opts)
|
||||
if err != nil {
|
||||
t.Fatalf("sqlc generate failed: %s", stderr.String())
|
||||
}
|
||||
cmpDirectory(t, path, output)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExamples(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
examples, err := filepath.Abs(filepath.Join("..", "..", "examples"))
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
files, err := os.ReadDir(examples)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
for _, replay := range files {
|
||||
if !replay.IsDir() {
|
||||
continue
|
||||
}
|
||||
tc := replay.Name()
|
||||
b.Run(tc, func(b *testing.B) {
|
||||
path := filepath.Join(examples, tc)
|
||||
for i := 0; i < b.N; i++ {
|
||||
var stderr bytes.Buffer
|
||||
opts := &cmd.Options{
|
||||
Env: cmd.Env{},
|
||||
Stderr: &stderr,
|
||||
}
|
||||
cmd.Generate(ctx, path, "", opts)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type textContext struct {
|
||||
Mutate func(*testing.T, string) func(*config.Config)
|
||||
Enabled func() bool
|
||||
// Experiments names the experiments every case in this context runs
|
||||
// with. A case's own SQLCEXPERIMENT is appended to these, so a case can
|
||||
// still turn one back off with the "no" prefix.
|
||||
Experiments func() []string
|
||||
}
|
||||
|
||||
func TestReplay(t *testing.T) {
|
||||
// Ensure that this environment variable is always set to true when running
|
||||
// end-to-end tests
|
||||
os.Setenv("SQLC_DUMMY_VALUE", "true")
|
||||
|
||||
// t.Parallel()
|
||||
ctx := context.Background()
|
||||
|
||||
var mysqlURI, postgresURI string
|
||||
|
||||
// First, check environment variables
|
||||
if uri := os.Getenv("POSTGRESQL_SERVER_URI"); uri != "" {
|
||||
postgresURI = uri
|
||||
}
|
||||
if uri := os.Getenv("MYSQL_SERVER_URI"); uri != "" {
|
||||
mysqlURI = uri
|
||||
}
|
||||
|
||||
// Try Docker for any missing databases
|
||||
if postgresURI == "" || mysqlURI == "" {
|
||||
if err := docker.Installed(); err == nil {
|
||||
if postgresURI == "" {
|
||||
host, err := docker.StartPostgreSQLServer(ctx)
|
||||
if err != nil {
|
||||
t.Logf("docker postgresql startup failed: %s", err)
|
||||
} else {
|
||||
postgresURI = host
|
||||
}
|
||||
}
|
||||
if mysqlURI == "" {
|
||||
host, err := docker.StartMySQLServer(ctx)
|
||||
if err != nil {
|
||||
t.Logf("docker mysql startup failed: %s", err)
|
||||
} else {
|
||||
mysqlURI = host
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try native installation for any missing databases (Linux only)
|
||||
if postgresURI == "" || mysqlURI == "" {
|
||||
if err := native.Supported(); err == nil {
|
||||
if postgresURI == "" {
|
||||
host, err := native.StartPostgreSQLServer(ctx)
|
||||
if err != nil {
|
||||
t.Logf("native postgresql startup failed: %s", err)
|
||||
} else {
|
||||
postgresURI = host
|
||||
}
|
||||
}
|
||||
if mysqlURI == "" {
|
||||
host, err := native.StartMySQLServer(ctx)
|
||||
if err != nil {
|
||||
t.Logf("native mysql startup failed: %s", err)
|
||||
} else {
|
||||
mysqlURI = host
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log which databases are available
|
||||
t.Logf("PostgreSQL available: %v (URI: %s)", postgresURI != "", postgresURI)
|
||||
t.Logf("MySQL available: %v (URI: %s)", mysqlURI != "", mysqlURI)
|
||||
|
||||
contexts := map[string]textContext{
|
||||
"base": {
|
||||
Mutate: func(t *testing.T, path string) func(*config.Config) { return func(c *config.Config) {} },
|
||||
Enabled: func() bool { return true },
|
||||
},
|
||||
"managed-db": {
|
||||
Mutate: func(t *testing.T, path string) func(*config.Config) {
|
||||
return func(c *config.Config) {
|
||||
// Add all servers - tests will fail if database isn't available
|
||||
c.Servers = []config.Server{
|
||||
{
|
||||
Name: "postgres",
|
||||
Engine: config.EnginePostgreSQL,
|
||||
URI: postgresURI,
|
||||
},
|
||||
{
|
||||
Name: "mysql",
|
||||
Engine: config.EngineMySQL,
|
||||
URI: mysqlURI,
|
||||
},
|
||||
}
|
||||
|
||||
for i := range c.SQL {
|
||||
switch c.SQL[i].Engine {
|
||||
case config.EnginePostgreSQL:
|
||||
c.SQL[i].Database = &config.Database{
|
||||
Managed: true,
|
||||
}
|
||||
case config.EngineMySQL:
|
||||
c.SQL[i].Database = &config.Database{
|
||||
Managed: true,
|
||||
}
|
||||
case config.EngineSQLite:
|
||||
c.SQL[i].Database = &config.Database{
|
||||
Managed: true,
|
||||
}
|
||||
default:
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Enabled: func() bool {
|
||||
// Enabled if at least one database URI is available
|
||||
return postgresURI != "" || mysqlURI != ""
|
||||
},
|
||||
},
|
||||
"core": {
|
||||
Mutate: func(t *testing.T, path string) func(*config.Config) { return func(c *config.Config) {} },
|
||||
Experiments: func() []string { return []string{"coreanalyzer"} },
|
||||
Enabled: func() bool {
|
||||
// Running the whole corpus through the analysis core is opt-in
|
||||
// while the two paths still disagree. The core needs no
|
||||
// database, so nothing else gates this.
|
||||
return os.Getenv("SQLC_TEST_CORE") != ""
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testctx := range contexts {
|
||||
|
||||
if !testctx.Enabled() {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, replay := range FindTests(t, "testdata", name) {
|
||||
tc := replay
|
||||
t.Run(filepath.Join(name, tc.Name), func(t *testing.T) {
|
||||
var stderr bytes.Buffer
|
||||
var output map[string]string
|
||||
var err error
|
||||
|
||||
path, _ := filepath.Abs(tc.Path)
|
||||
args := tc.Exec
|
||||
if args == nil {
|
||||
args = &Exec{Command: "generate"}
|
||||
}
|
||||
expected := string(tc.Stderr)
|
||||
|
||||
if args.Process != "" {
|
||||
_, err := osexec.LookPath(args.Process)
|
||||
if err != nil {
|
||||
t.Skipf("executable not found: %s %s", args.Process, err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(args.Contexts) > 0 {
|
||||
if !slices.Contains(args.Contexts, name) {
|
||||
t.Skipf("unsupported context: %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
if len(args.OS) > 0 {
|
||||
if !slices.Contains(args.OS, runtime.GOOS) {
|
||||
t.Skipf("unsupported os: %s", runtime.GOOS)
|
||||
}
|
||||
}
|
||||
|
||||
experiments := args.Env["SQLCEXPERIMENT"]
|
||||
if testctx.Experiments != nil {
|
||||
experiments = strings.Join(append(testctx.Experiments(), experiments), ",")
|
||||
}
|
||||
|
||||
opts := cmd.Options{
|
||||
Env: cmd.Env{
|
||||
Experiment: opts.ExperimentFromString(experiments),
|
||||
},
|
||||
Stderr: &stderr,
|
||||
MutateConfig: testctx.Mutate(t, path),
|
||||
}
|
||||
|
||||
release := withSQLCDEBUG(t, args.Env["SQLCDEBUG"])
|
||||
defer release()
|
||||
|
||||
switch args.Command {
|
||||
case "diff":
|
||||
err = cmd.Diff(ctx, path, "", &opts)
|
||||
case "generate":
|
||||
output, err = cmd.Generate(ctx, path, "", &opts)
|
||||
if err == nil {
|
||||
cmpDirectory(t, path, output)
|
||||
}
|
||||
case "vet":
|
||||
err = cmd.Vet(ctx, path, "", &opts)
|
||||
case "parse", "analyze", "fmt":
|
||||
// These commands are flag-driven (fmt cases pass --diff so
|
||||
// nothing is rewritten). Run them through the real CLI
|
||||
// entry point from inside the test directory so file
|
||||
// arguments resolve and the output stays independent of
|
||||
// the absolute path.
|
||||
var stdout bytes.Buffer
|
||||
wd, werr := os.Getwd()
|
||||
if werr != nil {
|
||||
t.Fatal(werr)
|
||||
}
|
||||
if cerr := os.Chdir(path); cerr != nil {
|
||||
t.Fatal(cerr)
|
||||
}
|
||||
code := cmd.Do(append([]string{args.Command}, args.Args...), nil, &stdout, &stderr)
|
||||
if cerr := os.Chdir(wd); cerr != nil {
|
||||
t.Fatal(cerr)
|
||||
}
|
||||
if code != 0 {
|
||||
err = fmt.Errorf("%s exited with code %d", args.Command, code)
|
||||
} else if diff := cmp.Diff(strings.TrimSpace(string(tc.Stdout)), strings.TrimSpace(stdout.String()), lineEndings()); diff != "" {
|
||||
t.Errorf("stdout differed (-want +got):\n%s", diff)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unknown command")
|
||||
}
|
||||
|
||||
if len(expected) == 0 && err != nil {
|
||||
t.Fatalf("sqlc %s failed: %s", args.Command, stderr.String())
|
||||
}
|
||||
|
||||
diff := cmp.Diff(
|
||||
strings.TrimSpace(expected),
|
||||
strings.TrimSpace(stderr.String()),
|
||||
stderrTransformer(),
|
||||
)
|
||||
if diff != "" {
|
||||
t.Fatalf("stderr differed (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cmpDirectory(t *testing.T, dir string, actual map[string]string) {
|
||||
expected := map[string]string{}
|
||||
var ff = func(path string, file os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if file.IsDir() {
|
||||
return nil
|
||||
}
|
||||
if !strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, ".kt") && !strings.HasSuffix(path, ".py") && !strings.HasSuffix(path, ".json") && !strings.HasSuffix(path, ".txt") {
|
||||
return nil
|
||||
}
|
||||
// TODO: Figure out a better way to ignore certain files
|
||||
if strings.HasSuffix(path, ".txt") && filepath.Base(path) != "hello.txt" {
|
||||
return nil
|
||||
}
|
||||
if filepath.Base(path) == "sqlc.json" {
|
||||
return nil
|
||||
}
|
||||
if filepath.Base(path) == "exec.json" {
|
||||
return nil
|
||||
}
|
||||
if strings.Contains(path, "/kotlin/build") {
|
||||
return nil
|
||||
}
|
||||
if strings.HasSuffix(path, "_test.go") || strings.Contains(path, "src/test/") {
|
||||
return nil
|
||||
}
|
||||
if strings.Contains(path, "/python/.venv") || strings.Contains(path, "/python/src/tests/") ||
|
||||
strings.HasSuffix(path, "__init__.py") || strings.Contains(path, "/python/src/dbtest/") ||
|
||||
strings.Contains(path, "/python/.mypy_cache") {
|
||||
return nil
|
||||
}
|
||||
blob, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
expected[path] = string(blob)
|
||||
return nil
|
||||
}
|
||||
if err := filepath.Walk(dir, ff); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
opts := []cmp.Option{
|
||||
cmpopts.EquateEmpty(),
|
||||
lineEndings(),
|
||||
}
|
||||
|
||||
if !cmp.Equal(expected, actual, opts...) {
|
||||
t.Errorf("%s contents differ", dir)
|
||||
for name, contents := range expected {
|
||||
if actual[name] == "" {
|
||||
t.Errorf("%s is empty", name)
|
||||
return
|
||||
}
|
||||
if diff := cmp.Diff(contents, actual[name], opts...); diff != "" {
|
||||
t.Errorf("%s differed (-want +got):\n%s", name, diff)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReplay(b *testing.B) {
|
||||
ctx := context.Background()
|
||||
var dirs []string
|
||||
err := filepath.Walk("testdata", func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.Name() == "sqlc.json" || info.Name() == "sqlc.yaml" || info.Name() == "sqlc.yml" {
|
||||
dirs = append(dirs, filepath.Dir(path))
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
for _, replay := range dirs {
|
||||
tc := replay
|
||||
b.Run(tc, func(b *testing.B) {
|
||||
path, _ := filepath.Abs(tc)
|
||||
for i := 0; i < b.N; i++ {
|
||||
var stderr bytes.Buffer
|
||||
opts := &cmd.Options{
|
||||
Env: cmd.Env{},
|
||||
Stderr: &stderr,
|
||||
}
|
||||
cmd.Generate(ctx, path, "", opts)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
194
internal/endtoend/fmt_test.go
Normal file
194
internal/endtoend/fmt_test.go
Normal file
@@ -0,0 +1,194 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/config"
|
||||
"github.com/sqlc-dev/sqlc/internal/debug"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/dolphin"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/postgresql"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/sqlite"
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/ast"
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/format"
|
||||
)
|
||||
|
||||
// sqlParser is an interface for SQL parsers
|
||||
type sqlParser interface {
|
||||
Parse(r io.Reader) ([]ast.Statement, error)
|
||||
}
|
||||
|
||||
// sqlFormatter is an interface for formatters
|
||||
type sqlFormatter interface {
|
||||
format.Dialect
|
||||
}
|
||||
|
||||
func TestFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, tc := range FindTests(t, "testdata", "base") {
|
||||
// Config-less command tests (parse, analyze) have no config to format.
|
||||
if tc.ConfigName == "" {
|
||||
continue
|
||||
}
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
// Parse the config file to determine the engine
|
||||
configPath := filepath.Join(tc.Path, tc.ConfigName)
|
||||
configFile, err := os.Open(configPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf, err := config.ParseConfig(configFile)
|
||||
configFile.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Skip if there are no SQL packages configured
|
||||
if len(conf.SQL) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
engine := conf.SQL[0].Engine
|
||||
|
||||
// Select the appropriate parser and fingerprint function based on engine
|
||||
var parse sqlParser
|
||||
var formatter sqlFormatter
|
||||
var fingerprint func(string) (string, error)
|
||||
|
||||
switch engine {
|
||||
case config.EnginePostgreSQL:
|
||||
pgParser := postgresql.NewParser()
|
||||
parse = pgParser
|
||||
formatter = pgParser
|
||||
fingerprint = postgresql.Fingerprint
|
||||
case config.EngineMySQL:
|
||||
mysqlParser := dolphin.NewParser()
|
||||
parse = mysqlParser
|
||||
formatter = mysqlParser
|
||||
// For MySQL, we use a "round-trip" fingerprint: parse the SQL, format it,
|
||||
// and return the formatted string. This tests that our formatting produces
|
||||
// valid SQL that parses to the same AST structure.
|
||||
fingerprint = func(sql string) (string, error) {
|
||||
stmts, err := mysqlParser.Parse(strings.NewReader(sql))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(stmts) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return ast.Format(stmts[0].Raw, mysqlParser), nil
|
||||
}
|
||||
case config.EngineSQLite:
|
||||
sqliteParser := sqlite.NewParser()
|
||||
parse = sqliteParser
|
||||
formatter = sqliteParser
|
||||
// For SQLite, we use the same "round-trip" fingerprint strategy as MySQL:
|
||||
// parse the SQL, format it, and return the formatted string.
|
||||
fingerprint = func(sql string) (string, error) {
|
||||
stmts, err := sqliteParser.Parse(strings.NewReader(sql))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(stmts) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
return strings.ToLower(ast.Format(stmts[0].Raw, sqliteParser)), nil
|
||||
}
|
||||
default:
|
||||
// Skip unsupported engines
|
||||
return
|
||||
}
|
||||
|
||||
// Find query files from config
|
||||
var queryFiles []string
|
||||
for _, sql := range conf.SQL {
|
||||
for _, q := range sql.Queries {
|
||||
queryPath := filepath.Join(tc.Path, q)
|
||||
info, err := os.Stat(queryPath)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if info.IsDir() {
|
||||
// If it's a directory, glob for .sql files
|
||||
matches, err := filepath.Glob(filepath.Join(queryPath, "*.sql"))
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
queryFiles = append(queryFiles, matches...)
|
||||
} else {
|
||||
queryFiles = append(queryFiles, queryPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(queryFiles) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
for _, queryFile := range queryFiles {
|
||||
if _, err := os.Stat(queryFile); os.IsNotExist(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
contents, err := os.ReadFile(queryFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Parse the entire file to get proper statement boundaries
|
||||
stmts, err := parse.Parse(bytes.NewReader(contents))
|
||||
if err != nil {
|
||||
// Skip files with parse errors (e.g., syntax_errors test cases)
|
||||
return
|
||||
}
|
||||
|
||||
for i, stmt := range stmts {
|
||||
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||
// Extract the original query text using statement location and length
|
||||
start := stmt.Raw.StmtLocation
|
||||
length := stmt.Raw.StmtLen
|
||||
if length == 0 {
|
||||
// If StmtLen is 0, it means the statement goes to the end of the input
|
||||
length = len(contents) - start
|
||||
}
|
||||
query := strings.TrimSpace(string(contents[start : start+length]))
|
||||
|
||||
expected, err := fingerprint(query)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if false {
|
||||
r, err := postgresql.Parse(query)
|
||||
debug.Dump(r, err)
|
||||
}
|
||||
|
||||
out := ast.Format(stmt.Raw, formatter)
|
||||
// An empty rendering is the formatter's signal that
|
||||
// the statement carries syntax the AST does not
|
||||
// model; sqlc fmt keeps such statements as written.
|
||||
if strings.TrimSpace(strings.TrimSuffix(strings.TrimSpace(out), ";")) == "" {
|
||||
t.Skip("statement has no faithful rendering")
|
||||
}
|
||||
actual, err := fingerprint(out)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if expected != actual {
|
||||
debug.Dump(stmt.Raw)
|
||||
t.Errorf("- %s", expected)
|
||||
t.Errorf("- %s", query)
|
||||
t.Errorf("+ %s", actual)
|
||||
t.Errorf("+ %s", out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
82
internal/endtoend/json_schema_test.go
Normal file
82
internal/endtoend/json_schema_test.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/xeipuuv/gojsonschema"
|
||||
)
|
||||
|
||||
type conf struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
func loadSchema(t *testing.T, path string) *gojsonschema.Schema {
|
||||
t.Helper()
|
||||
|
||||
schemaBytes, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
loader := gojsonschema.NewStringLoader(string(schemaBytes))
|
||||
schema, err := gojsonschema.NewSchema(loader)
|
||||
if err != nil {
|
||||
t.Fatalf("invalid schema: %s", err)
|
||||
}
|
||||
return schema
|
||||
}
|
||||
|
||||
func TestJsonSchema(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
schemaOne := loadSchema(t, filepath.Join("..", "config", "v_one.json"))
|
||||
schemaTwo := loadSchema(t, filepath.Join("..", "config", "v_two.json"))
|
||||
|
||||
srcs := []string{
|
||||
filepath.Join("..", "..", "examples"),
|
||||
filepath.Join("testdata"),
|
||||
}
|
||||
|
||||
for _, dir := range srcs {
|
||||
err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if filepath.Base(path) != "sqlc.json" {
|
||||
return nil
|
||||
}
|
||||
t.Run(path, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
contents, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var c conf
|
||||
if err := json.Unmarshal(contents, &c); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
l := gojsonschema.NewStringLoader(string(contents))
|
||||
switch c.Version {
|
||||
case "1":
|
||||
if _, err := schemaOne.Validate(l); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
case "2":
|
||||
if _, err := schemaTwo.Validate(l); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
default:
|
||||
t.Fatalf("unknown schema version: %s", c.Version)
|
||||
}
|
||||
})
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
31
internal/endtoend/testdata/alias/mysql/go/db.go
vendored
Normal file
31
internal/endtoend/testdata/alias/mysql/go/db.go
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...any) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...any) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
9
internal/endtoend/testdata/alias/mysql/go/models.go
vendored
Normal file
9
internal/endtoend/testdata/alias/mysql/go/models.go
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
type Bar struct {
|
||||
ID uint64
|
||||
}
|
||||
20
internal/endtoend/testdata/alias/mysql/go/query.sql.go
vendored
Normal file
20
internal/endtoend/testdata/alias/mysql/go/query.sql.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: query.sql
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const aliasBar = `-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) AliasBar(ctx context.Context, id uint64) error {
|
||||
_, err := q.db.ExecContext(ctx, aliasBar, id)
|
||||
return err
|
||||
}
|
||||
3
internal/endtoend/testdata/alias/mysql/query.sql
vendored
Normal file
3
internal/endtoend/testdata/alias/mysql/query.sql
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = ?;
|
||||
2
internal/endtoend/testdata/alias/mysql/schema.sql
vendored
Normal file
2
internal/endtoend/testdata/alias/mysql/schema.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE bar (id serial not null);
|
||||
|
||||
12
internal/endtoend/testdata/alias/mysql/sqlc.json
vendored
Normal file
12
internal/endtoend/testdata/alias/mysql/sqlc.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "1",
|
||||
"packages": [
|
||||
{
|
||||
"path": "go",
|
||||
"engine": "mysql",
|
||||
"name": "querytest",
|
||||
"schema": "schema.sql",
|
||||
"queries": "query.sql"
|
||||
}
|
||||
]
|
||||
}
|
||||
32
internal/endtoend/testdata/alias/postgresql/pgx/v4/go/db.go
vendored
Normal file
32
internal/endtoend/testdata/alias/postgresql/pgx/v4/go/db.go
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgconn"
|
||||
"github.com/jackc/pgx/v4"
|
||||
)
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
9
internal/endtoend/testdata/alias/postgresql/pgx/v4/go/models.go
vendored
Normal file
9
internal/endtoend/testdata/alias/postgresql/pgx/v4/go/models.go
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
type Bar struct {
|
||||
ID int32
|
||||
}
|
||||
20
internal/endtoend/testdata/alias/postgresql/pgx/v4/go/query.sql.go
vendored
Normal file
20
internal/endtoend/testdata/alias/postgresql/pgx/v4/go/query.sql.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: query.sql
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const aliasBar = `-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) AliasBar(ctx context.Context, id int32) error {
|
||||
_, err := q.db.Exec(ctx, aliasBar, id)
|
||||
return err
|
||||
}
|
||||
3
internal/endtoend/testdata/alias/postgresql/pgx/v4/query.sql
vendored
Normal file
3
internal/endtoend/testdata/alias/postgresql/pgx/v4/query.sql
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = $1;
|
||||
2
internal/endtoend/testdata/alias/postgresql/pgx/v4/schema.sql
vendored
Normal file
2
internal/endtoend/testdata/alias/postgresql/pgx/v4/schema.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE bar (id serial not null);
|
||||
|
||||
13
internal/endtoend/testdata/alias/postgresql/pgx/v4/sqlc.json
vendored
Normal file
13
internal/endtoend/testdata/alias/postgresql/pgx/v4/sqlc.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "1",
|
||||
"packages": [
|
||||
{
|
||||
"path": "go",
|
||||
"engine": "postgresql",
|
||||
"sql_package": "pgx/v4",
|
||||
"name": "querytest",
|
||||
"schema": "schema.sql",
|
||||
"queries": "query.sql"
|
||||
}
|
||||
]
|
||||
}
|
||||
32
internal/endtoend/testdata/alias/postgresql/pgx/v5/go/db.go
vendored
Normal file
32
internal/endtoend/testdata/alias/postgresql/pgx/v5/go/db.go
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
9
internal/endtoend/testdata/alias/postgresql/pgx/v5/go/models.go
vendored
Normal file
9
internal/endtoend/testdata/alias/postgresql/pgx/v5/go/models.go
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
type Bar struct {
|
||||
ID int32
|
||||
}
|
||||
20
internal/endtoend/testdata/alias/postgresql/pgx/v5/go/query.sql.go
vendored
Normal file
20
internal/endtoend/testdata/alias/postgresql/pgx/v5/go/query.sql.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: query.sql
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const aliasBar = `-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) AliasBar(ctx context.Context, id int32) error {
|
||||
_, err := q.db.Exec(ctx, aliasBar, id)
|
||||
return err
|
||||
}
|
||||
3
internal/endtoend/testdata/alias/postgresql/pgx/v5/query.sql
vendored
Normal file
3
internal/endtoend/testdata/alias/postgresql/pgx/v5/query.sql
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = $1;
|
||||
2
internal/endtoend/testdata/alias/postgresql/pgx/v5/schema.sql
vendored
Normal file
2
internal/endtoend/testdata/alias/postgresql/pgx/v5/schema.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE bar (id serial not null);
|
||||
|
||||
13
internal/endtoend/testdata/alias/postgresql/pgx/v5/sqlc.json
vendored
Normal file
13
internal/endtoend/testdata/alias/postgresql/pgx/v5/sqlc.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "1",
|
||||
"packages": [
|
||||
{
|
||||
"path": "go",
|
||||
"engine": "postgresql",
|
||||
"sql_package": "pgx/v5",
|
||||
"name": "querytest",
|
||||
"schema": "schema.sql",
|
||||
"queries": "query.sql"
|
||||
}
|
||||
]
|
||||
}
|
||||
31
internal/endtoend/testdata/alias/postgresql/stdlib/go/db.go
vendored
Normal file
31
internal/endtoend/testdata/alias/postgresql/stdlib/go/db.go
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...any) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...any) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
9
internal/endtoend/testdata/alias/postgresql/stdlib/go/models.go
vendored
Normal file
9
internal/endtoend/testdata/alias/postgresql/stdlib/go/models.go
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
type Bar struct {
|
||||
ID int32
|
||||
}
|
||||
20
internal/endtoend/testdata/alias/postgresql/stdlib/go/query.sql.go
vendored
Normal file
20
internal/endtoend/testdata/alias/postgresql/stdlib/go/query.sql.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: query.sql
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const aliasBar = `-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = $1
|
||||
`
|
||||
|
||||
func (q *Queries) AliasBar(ctx context.Context, id int32) error {
|
||||
_, err := q.db.ExecContext(ctx, aliasBar, id)
|
||||
return err
|
||||
}
|
||||
3
internal/endtoend/testdata/alias/postgresql/stdlib/query.sql
vendored
Normal file
3
internal/endtoend/testdata/alias/postgresql/stdlib/query.sql
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
-- name: AliasBar :exec
|
||||
DELETE FROM bar b
|
||||
WHERE b.id = $1;
|
||||
1
internal/endtoend/testdata/alias/postgresql/stdlib/schema.sql
vendored
Normal file
1
internal/endtoend/testdata/alias/postgresql/stdlib/schema.sql
vendored
Normal file
@@ -0,0 +1 @@
|
||||
CREATE TABLE bar (id serial not null);
|
||||
12
internal/endtoend/testdata/alias/postgresql/stdlib/sqlc.json
vendored
Normal file
12
internal/endtoend/testdata/alias/postgresql/stdlib/sqlc.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "1",
|
||||
"packages": [
|
||||
{
|
||||
"path": "go",
|
||||
"engine": "postgresql",
|
||||
"name": "querytest",
|
||||
"schema": "schema.sql",
|
||||
"queries": "query.sql"
|
||||
}
|
||||
]
|
||||
}
|
||||
31
internal/endtoend/testdata/alias/sqlite/go/db.go
vendored
Normal file
31
internal/endtoend/testdata/alias/sqlite/go/db.go
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
ExecContext(context.Context, string, ...any) (sql.Result, error)
|
||||
PrepareContext(context.Context, string) (*sql.Stmt, error)
|
||||
QueryContext(context.Context, string, ...any) (*sql.Rows, error)
|
||||
QueryRowContext(context.Context, string, ...any) *sql.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
||||
9
internal/endtoend/testdata/alias/sqlite/go/models.go
vendored
Normal file
9
internal/endtoend/testdata/alias/sqlite/go/models.go
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
|
||||
package querytest
|
||||
|
||||
type Bar struct {
|
||||
ID int64
|
||||
}
|
||||
20
internal/endtoend/testdata/alias/sqlite/go/query.sql.go
vendored
Normal file
20
internal/endtoend/testdata/alias/sqlite/go/query.sql.go
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.31.1
|
||||
// source: query.sql
|
||||
|
||||
package querytest
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const aliasBar = `-- name: AliasBar :exec
|
||||
DELETE FROM bar AS b
|
||||
WHERE b.id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) AliasBar(ctx context.Context, id int64) error {
|
||||
_, err := q.db.ExecContext(ctx, aliasBar, id)
|
||||
return err
|
||||
}
|
||||
3
internal/endtoend/testdata/alias/sqlite/query.sql
vendored
Normal file
3
internal/endtoend/testdata/alias/sqlite/query.sql
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
-- name: AliasBar :exec
|
||||
DELETE FROM bar AS b
|
||||
WHERE b.id = ?;
|
||||
2
internal/endtoend/testdata/alias/sqlite/schema.sql
vendored
Normal file
2
internal/endtoend/testdata/alias/sqlite/schema.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
CREATE TABLE bar (id integer NOT NULL PRIMARY KEY AUTOINCREMENT);
|
||||
|
||||
12
internal/endtoend/testdata/alias/sqlite/sqlc.json
vendored
Normal file
12
internal/endtoend/testdata/alias/sqlite/sqlc.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"version": "1",
|
||||
"packages": [
|
||||
{
|
||||
"path": "go",
|
||||
"engine": "sqlite",
|
||||
"name": "querytest",
|
||||
"schema": "schema.sql",
|
||||
"queries": "query.sql"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
internal/endtoend/testdata/analyze_ast/postgresql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_ast/postgresql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "postgresql", "--schema", "schema.sql", "--ast", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_ast/postgresql/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_ast/postgresql/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: GetAuthorName :one
|
||||
SELECT name FROM authors WHERE id = $1;
|
||||
5
internal/endtoend/testdata/analyze_ast/postgresql/schema.sql
vendored
Normal file
5
internal/endtoend/testdata/analyze_ast/postgresql/schema.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE authors (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name text NOT NULL,
|
||||
bio text
|
||||
);
|
||||
136
internal/endtoend/testdata/analyze_ast/postgresql/stdout.json
vendored
Normal file
136
internal/endtoend/testdata/analyze_ast/postgresql/stdout.json
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
[
|
||||
{
|
||||
"name": "GetAuthorName",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
],
|
||||
"ast": {
|
||||
"tag": "RawStmt",
|
||||
"stmt": {
|
||||
"tag": "SelectStmt",
|
||||
"distinct_clause": {
|
||||
"tag": "List"
|
||||
},
|
||||
"target_list": {
|
||||
"tag": "List",
|
||||
"items": [
|
||||
{
|
||||
"tag": "ResTarget",
|
||||
"indirection": {
|
||||
"tag": "List"
|
||||
},
|
||||
"val": {
|
||||
"tag": "ColumnRef",
|
||||
"name": "",
|
||||
"fields": {
|
||||
"tag": "List",
|
||||
"items": [
|
||||
{
|
||||
"tag": "String",
|
||||
"str": "name"
|
||||
}
|
||||
]
|
||||
},
|
||||
"location": 35
|
||||
},
|
||||
"location": 35
|
||||
}
|
||||
]
|
||||
},
|
||||
"from_clause": {
|
||||
"tag": "List",
|
||||
"items": [
|
||||
{
|
||||
"tag": "RangeVar",
|
||||
"relname": "authors",
|
||||
"inh": true,
|
||||
"relpersistence": 112,
|
||||
"location": 45
|
||||
}
|
||||
]
|
||||
},
|
||||
"where_clause": {
|
||||
"tag": "A_Expr",
|
||||
"kind": 1,
|
||||
"name": {
|
||||
"tag": "List",
|
||||
"items": [
|
||||
{
|
||||
"tag": "String",
|
||||
"str": "="
|
||||
}
|
||||
]
|
||||
},
|
||||
"lexpr": {
|
||||
"tag": "ColumnRef",
|
||||
"name": "",
|
||||
"fields": {
|
||||
"tag": "List",
|
||||
"items": [
|
||||
{
|
||||
"tag": "String",
|
||||
"str": "id"
|
||||
}
|
||||
]
|
||||
},
|
||||
"location": 59
|
||||
},
|
||||
"rexpr": {
|
||||
"tag": "ParamRef",
|
||||
"number": 1,
|
||||
"location": 64,
|
||||
"dollar": true
|
||||
},
|
||||
"location": 62
|
||||
},
|
||||
"group_clause": {
|
||||
"tag": "List"
|
||||
},
|
||||
"having_clause": {
|
||||
"tag": "TODO"
|
||||
},
|
||||
"window_clause": {
|
||||
"tag": "List"
|
||||
},
|
||||
"values_lists": {
|
||||
"tag": "List"
|
||||
},
|
||||
"sort_clause": {
|
||||
"tag": "List"
|
||||
},
|
||||
"limit_offset": {
|
||||
"tag": "TODO"
|
||||
},
|
||||
"limit_count": {
|
||||
"tag": "TODO"
|
||||
},
|
||||
"locking_clause": {
|
||||
"tag": "List"
|
||||
},
|
||||
"op": 0,
|
||||
"all": false
|
||||
},
|
||||
"stmt_location": 0,
|
||||
"stmt_len": 66
|
||||
}
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/clickhouse/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/clickhouse/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "clickhouse", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
1
internal/endtoend/testdata/analyze_basic/clickhouse/fixture.sql
vendored
Normal file
1
internal/endtoend/testdata/analyze_basic/clickhouse/fixture.sql
vendored
Normal file
@@ -0,0 +1 @@
|
||||
INSERT INTO events (id, name, tag, amount, created) VALUES (1, 'signup', NULL, 9.5, '2024-01-01 00:00:00');
|
||||
2
internal/endtoend/testdata/analyze_basic/clickhouse/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/clickhouse/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: ListEvents :many
|
||||
SELECT id, name, tag, amount, created FROM events;
|
||||
7
internal/endtoend/testdata/analyze_basic/clickhouse/schema.sql
vendored
Normal file
7
internal/endtoend/testdata/analyze_basic/clickhouse/schema.sql
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE events (
|
||||
id UInt64,
|
||||
name String,
|
||||
tag Nullable(String),
|
||||
amount Float64,
|
||||
created DateTime
|
||||
) ENGINE = MergeTree ORDER BY id;
|
||||
45
internal/endtoend/testdata/analyze_basic/clickhouse/stdout.json
vendored
Normal file
45
internal/endtoend/testdata/analyze_basic/clickhouse/stdout.json
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
[
|
||||
{
|
||||
"name": "ListEvents",
|
||||
"cmd": ":many",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "uint64"
|
||||
},
|
||||
"table": "events"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string"
|
||||
},
|
||||
"table": "events"
|
||||
},
|
||||
{
|
||||
"name": "tag",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "events"
|
||||
},
|
||||
{
|
||||
"name": "amount",
|
||||
"type": {
|
||||
"name": "float64"
|
||||
},
|
||||
"table": "events"
|
||||
},
|
||||
{
|
||||
"name": "created",
|
||||
"type": {
|
||||
"name": "datetime"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
],
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/duckdb/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/duckdb/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "duckdb", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_basic/duckdb/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/duckdb/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: ListAuthors :many
|
||||
SELECT id, name, bio, royalties, created FROM authors;
|
||||
7
internal/endtoend/testdata/analyze_basic/duckdb/schema.sql
vendored
Normal file
7
internal/endtoend/testdata/analyze_basic/duckdb/schema.sql
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE authors (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
bio TEXT,
|
||||
royalties DECIMAL(10,2) NOT NULL,
|
||||
created TIMESTAMP NOT NULL
|
||||
);
|
||||
53
internal/endtoend/testdata/analyze_basic/duckdb/stdout.json
vendored
Normal file
53
internal/endtoend/testdata/analyze_basic/duckdb/stdout.json
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
[
|
||||
{
|
||||
"name": "ListAuthors",
|
||||
"cmd": ":many",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar"
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "varchar",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "royalties",
|
||||
"type": {
|
||||
"name": "decimal",
|
||||
"args": [
|
||||
{
|
||||
"int": 10
|
||||
},
|
||||
{
|
||||
"int": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "created",
|
||||
"type": {
|
||||
"name": "timestamp"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
],
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/googlesql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/googlesql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "googlesql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_basic/googlesql/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/googlesql/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: GetUser :one
|
||||
SELECT id, name FROM users WHERE id = @id;
|
||||
5
internal/endtoend/testdata/analyze_basic/googlesql/schema.sql
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/googlesql/schema.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE users (
|
||||
id INT64 NOT NULL,
|
||||
name STRING(MAX) NOT NULL,
|
||||
bio STRING(MAX),
|
||||
) PRIMARY KEY (id);
|
||||
39
internal/endtoend/testdata/analyze_basic/googlesql/stdout.json
vendored
Normal file
39
internal/endtoend/testdata/analyze_basic/googlesql/stdout.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
[
|
||||
{
|
||||
"name": "GetUser",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/mssql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/mssql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "mssql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_basic/mssql/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/mssql/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: ListAuthors :many
|
||||
SELECT id, name, bio, royalties, created FROM authors;
|
||||
7
internal/endtoend/testdata/analyze_basic/mssql/schema.sql
vendored
Normal file
7
internal/endtoend/testdata/analyze_basic/mssql/schema.sql
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE authors (
|
||||
id BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||
name NVARCHAR(100) NOT NULL,
|
||||
bio NVARCHAR(MAX),
|
||||
royalties DECIMAL(10,2) NOT NULL,
|
||||
created DATETIME2 NOT NULL
|
||||
);
|
||||
68
internal/endtoend/testdata/analyze_basic/mssql/stdout.json
vendored
Normal file
68
internal/endtoend/testdata/analyze_basic/mssql/stdout.json
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
[
|
||||
{
|
||||
"name": "ListAuthors",
|
||||
"cmd": ":many",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"nullable": true,
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "royalties",
|
||||
"type": {
|
||||
"name": "decimal",
|
||||
"args": [
|
||||
{
|
||||
"int": 10
|
||||
},
|
||||
{
|
||||
"int": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "created",
|
||||
"type": {
|
||||
"name": "datetime2",
|
||||
"args": [
|
||||
{
|
||||
"int": 7
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
],
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/mysql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/mysql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "mysql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_basic/mysql/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/mysql/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: GetUser :one
|
||||
SELECT id, name FROM users WHERE id = ?;
|
||||
5
internal/endtoend/testdata/analyze_basic/mysql/schema.sql
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/mysql/schema.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE users (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
bio TEXT
|
||||
);
|
||||
39
internal/endtoend/testdata/analyze_basic/mysql/stdout.json
vendored
Normal file
39
internal/endtoend/testdata/analyze_basic/mysql/stdout.json
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
[
|
||||
{
|
||||
"name": "GetUser",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 255
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/postgresql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/postgresql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "postgresql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_basic/postgresql/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/postgresql/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: GetAuthor :one
|
||||
SELECT * FROM authors WHERE id = $1;
|
||||
5
internal/endtoend/testdata/analyze_basic/postgresql/schema.sql
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/postgresql/schema.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE authors (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name text NOT NULL,
|
||||
bio text
|
||||
);
|
||||
42
internal/endtoend/testdata/analyze_basic/postgresql/stdout.json
vendored
Normal file
42
internal/endtoend/testdata/analyze_basic/postgresql/stdout.json
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
[
|
||||
{
|
||||
"name": "GetAuthor",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "authors"
|
||||
},
|
||||
{
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_basic/sqlite/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/sqlite/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "sqlite", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_basic/sqlite/query.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_basic/sqlite/query.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
-- name: GetUser :one
|
||||
SELECT id, name FROM users WHERE id = ?;
|
||||
5
internal/endtoend/testdata/analyze_basic/sqlite/schema.sql
vendored
Normal file
5
internal/endtoend/testdata/analyze_basic/sqlite/schema.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
age INTEGER
|
||||
);
|
||||
34
internal/endtoend/testdata/analyze_basic/sqlite/stdout.json
vendored
Normal file
34
internal/endtoend/testdata/analyze_basic/sqlite/stdout.json
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"name": "GetUser",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "integer"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "integer"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_dml/duckdb/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/duckdb/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "duckdb", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
13
internal/endtoend/testdata/analyze_dml/duckdb/query.sql
vendored
Normal file
13
internal/endtoend/testdata/analyze_dml/duckdb/query.sql
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
-- name: CreateAuthor :one
|
||||
INSERT INTO authors (id, name, bio) VALUES ($1, $2, $3) RETURNING id;
|
||||
|
||||
-- name: UpdateAuthor :exec
|
||||
UPDATE authors SET name = $name, bio = $bio WHERE id = $id;
|
||||
|
||||
-- name: DeleteBooksByAuthor :exec
|
||||
DELETE FROM books USING authors a WHERE books.author_id = a.id AND a.name = $1;
|
||||
|
||||
-- name: TitlesFromBooks :many
|
||||
INSERT INTO books (id, author_id, title)
|
||||
SELECT id + 1000, author_id, upper(title) FROM books WHERE price > $min_price
|
||||
RETURNING id, title;
|
||||
12
internal/endtoend/testdata/analyze_dml/duckdb/schema.sql
vendored
Normal file
12
internal/endtoend/testdata/analyze_dml/duckdb/schema.sql
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE authors (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
bio TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE books (
|
||||
id BIGINT PRIMARY KEY,
|
||||
author_id BIGINT NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
price DECIMAL(10,2)
|
||||
);
|
||||
144
internal/endtoend/testdata/analyze_dml/duckdb/stdout.json
vendored
Normal file
144
internal/endtoend/testdata/analyze_dml/duckdb/stdout.json
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateAuthor",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "varchar",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateAuthor",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "varchar",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteBooksByAuthor",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "TitlesFromBooks",
|
||||
"cmd": ":many",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "books"
|
||||
},
|
||||
{
|
||||
"name": "title",
|
||||
"type": {
|
||||
"name": "varchar"
|
||||
},
|
||||
"table": "books"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "price",
|
||||
"type": {
|
||||
"name": "decimal",
|
||||
"nullable": true,
|
||||
"args": [
|
||||
{
|
||||
"int": 10
|
||||
},
|
||||
{
|
||||
"int": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "books"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_dml/googlesql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/googlesql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "googlesql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
17
internal/endtoend/testdata/analyze_dml/googlesql/query.sql
vendored
Normal file
17
internal/endtoend/testdata/analyze_dml/googlesql/query.sql
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
-- name: CreateUser :exec
|
||||
INSERT INTO users (id, name, bio) VALUES (@id, @name, @bio);
|
||||
|
||||
-- name: CreateUserReturning :one
|
||||
INSERT INTO users (id, name) VALUES (@id, @name) THEN RETURN id, name;
|
||||
|
||||
-- name: UpdateBio :exec
|
||||
UPDATE users SET bio = @bio WHERE id = @id;
|
||||
|
||||
-- name: UpdateNameReturning :one
|
||||
UPDATE users SET name = @name WHERE id = @id THEN RETURN id, name;
|
||||
|
||||
-- name: DeleteUser :exec
|
||||
DELETE FROM users WHERE id = @id;
|
||||
|
||||
-- name: DeleteUserReturning :one
|
||||
DELETE FROM users WHERE id = @id THEN RETURN id;
|
||||
5
internal/endtoend/testdata/analyze_dml/googlesql/schema.sql
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/googlesql/schema.sql
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
CREATE TABLE users (
|
||||
id INT64 NOT NULL,
|
||||
name STRING(MAX) NOT NULL,
|
||||
bio STRING(MAX),
|
||||
) PRIMARY KEY (id);
|
||||
229
internal/endtoend/testdata/analyze_dml/googlesql/stdout.json
vendored
Normal file
229
internal/endtoend/testdata/analyze_dml/googlesql/stdout.json
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"nullable": true,
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CreateUserReturning",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateBio",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"nullable": true,
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateNameReturning",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUserReturning",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "int64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_dml/mssql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/mssql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "mssql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
11
internal/endtoend/testdata/analyze_dml/mssql/query.sql
vendored
Normal file
11
internal/endtoend/testdata/analyze_dml/mssql/query.sql
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
-- name: CreateAuthor :one
|
||||
INSERT INTO authors (name, bio) OUTPUT INSERTED.id VALUES (@name, @bio);
|
||||
|
||||
-- name: UpdateAuthorAlias :exec
|
||||
UPDATE a SET name = @name FROM authors a WHERE a.id = @id;
|
||||
|
||||
-- name: UpdateBookPrices :exec
|
||||
UPDATE b SET price = @price FROM books b JOIN authors a ON b.author_id = a.id WHERE a.name = @author;
|
||||
|
||||
-- name: DeleteBooksByAuthor :exec
|
||||
DELETE b FROM books b INNER JOIN authors a ON b.author_id = a.id WHERE a.name = @name;
|
||||
12
internal/endtoend/testdata/analyze_dml/mssql/schema.sql
vendored
Normal file
12
internal/endtoend/testdata/analyze_dml/mssql/schema.sql
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE authors (
|
||||
id BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||
name NVARCHAR(100) NOT NULL,
|
||||
bio NVARCHAR(MAX)
|
||||
);
|
||||
|
||||
CREATE TABLE books (
|
||||
id BIGINT IDENTITY(1,1) PRIMARY KEY,
|
||||
author_id BIGINT NOT NULL,
|
||||
title NVARCHAR(200) NOT NULL,
|
||||
price DECIMAL(10,2)
|
||||
);
|
||||
143
internal/endtoend/testdata/analyze_dml/mssql/stdout.json
vendored
Normal file
143
internal/endtoend/testdata/analyze_dml/mssql/stdout.json
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateAuthor",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"nullable": true,
|
||||
"args": [
|
||||
{
|
||||
"ident": "max"
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateAuthorAlias",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateBookPrices",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "price",
|
||||
"type": {
|
||||
"name": "decimal",
|
||||
"nullable": true,
|
||||
"args": [
|
||||
{
|
||||
"int": 10
|
||||
},
|
||||
{
|
||||
"int": 2
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "books"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteBooksByAuthor",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "nvarchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 100
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "authors"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_dml/mysql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/mysql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "mysql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
11
internal/endtoend/testdata/analyze_dml/mysql/query.sql
vendored
Normal file
11
internal/endtoend/testdata/analyze_dml/mysql/query.sql
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
-- name: CreateUser :exec
|
||||
INSERT INTO users (id, name, bio) VALUES (?, ?, ?);
|
||||
|
||||
-- name: UpdateBio :exec
|
||||
UPDATE users SET bio = ? WHERE id = ?;
|
||||
|
||||
-- name: DeleteUser :exec
|
||||
DELETE FROM users WHERE id = ?;
|
||||
|
||||
-- name: DeleteUserPosts :exec
|
||||
DELETE p FROM posts p JOIN users u ON u.id = p.user_id WHERE u.name = ?;
|
||||
12
internal/endtoend/testdata/analyze_dml/mysql/schema.sql
vendored
Normal file
12
internal/endtoend/testdata/analyze_dml/mysql/schema.sql
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE users (
|
||||
id BIGINT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
bio TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE posts (
|
||||
id BIGINT PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
title VARCHAR(255),
|
||||
created DATETIME NOT NULL
|
||||
);
|
||||
112
internal/endtoend/testdata/analyze_dml/mysql/stdout.json
vendored
Normal file
112
internal/endtoend/testdata/analyze_dml/mysql/stdout.json
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 255
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateBio",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUserPosts",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "varchar",
|
||||
"args": [
|
||||
{
|
||||
"int": 255
|
||||
}
|
||||
]
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_dml/postgresql/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/postgresql/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "postgresql", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
14
internal/endtoend/testdata/analyze_dml/postgresql/query.sql
vendored
Normal file
14
internal/endtoend/testdata/analyze_dml/postgresql/query.sql
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
-- name: CreateUser :one
|
||||
INSERT INTO users (name, bio) VALUES ($1, $2) RETURNING *;
|
||||
|
||||
-- name: UpdateBio :exec
|
||||
UPDATE users SET bio = $1 WHERE id = $2;
|
||||
|
||||
-- name: UpdateNameReturning :one
|
||||
UPDATE users SET name = $1 WHERE id = $2 RETURNING id, name;
|
||||
|
||||
-- name: DeleteUser :exec
|
||||
DELETE FROM users WHERE id = $1;
|
||||
|
||||
-- name: DeleteUserReturning :one
|
||||
DELETE FROM users WHERE id = $1 RETURNING id;
|
||||
12
internal/endtoend/testdata/analyze_dml/postgresql/schema.sql
vendored
Normal file
12
internal/endtoend/testdata/analyze_dml/postgresql/schema.sql
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE users (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
name text NOT NULL,
|
||||
bio text
|
||||
);
|
||||
|
||||
CREATE TABLE posts (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id bigint NOT NULL,
|
||||
title varchar(255),
|
||||
created timestamptz NOT NULL
|
||||
);
|
||||
165
internal/endtoend/testdata/analyze_dml/postgresql/stdout.json
vendored
Normal file
165
internal/endtoend/testdata/analyze_dml/postgresql/stdout.json
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateUser",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateBio",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateNameReturning",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUserReturning",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "bigint"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_dml/sqlite/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_dml/sqlite/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "sqlite", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
8
internal/endtoend/testdata/analyze_dml/sqlite/query.sql
vendored
Normal file
8
internal/endtoend/testdata/analyze_dml/sqlite/query.sql
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
-- name: CreateUser :one
|
||||
INSERT INTO users (name, bio) VALUES (?, ?) RETURNING *;
|
||||
|
||||
-- name: UpdateBio :exec
|
||||
UPDATE users SET bio = ? WHERE id = ?;
|
||||
|
||||
-- name: DeleteUser :exec
|
||||
DELETE FROM users WHERE id = ?;
|
||||
12
internal/endtoend/testdata/analyze_dml/sqlite/schema.sql
vendored
Normal file
12
internal/endtoend/testdata/analyze_dml/sqlite/schema.sql
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
CREATE TABLE users (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
bio TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE posts (
|
||||
id INTEGER PRIMARY KEY,
|
||||
user_id INTEGER NOT NULL,
|
||||
title TEXT,
|
||||
created TEXT NOT NULL
|
||||
);
|
||||
98
internal/endtoend/testdata/analyze_dml/sqlite/stdout.json
vendored
Normal file
98
internal/endtoend/testdata/analyze_dml/sqlite/stdout.json
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateUser",
|
||||
"cmd": ":one",
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "integer"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
},
|
||||
{
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "text"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "UpdateBio",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "bio",
|
||||
"type": {
|
||||
"name": "text",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "integer"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DeleteUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "integer"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_exec/clickhouse/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_exec/clickhouse/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "clickhouse", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_exec/clickhouse/fixture.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_exec/clickhouse/fixture.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
INSERT INTO events VALUES (1, 'signup', NULL, 9.5), (2, 'login', 'web', 0.5);
|
||||
INSERT INTO users VALUES (1, 'a@example.com');
|
||||
11
internal/endtoend/testdata/analyze_exec/clickhouse/query.sql
vendored
Normal file
11
internal/endtoend/testdata/analyze_exec/clickhouse/query.sql
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
-- name: CreateUser :exec
|
||||
INSERT INTO users (id, email) VALUES (?, ?);
|
||||
|
||||
-- name: CreateEvent :exec
|
||||
INSERT INTO events VALUES (?, ?, ?, ?);
|
||||
|
||||
-- name: CreateEvents :exec
|
||||
INSERT INTO events (id, name) VALUES (?, ?), (?, ?);
|
||||
|
||||
-- name: DropUsers :exec
|
||||
TRUNCATE TABLE users;
|
||||
11
internal/endtoend/testdata/analyze_exec/clickhouse/schema.sql
vendored
Normal file
11
internal/endtoend/testdata/analyze_exec/clickhouse/schema.sql
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
CREATE TABLE events (
|
||||
id UInt64,
|
||||
name String,
|
||||
tag Nullable(String),
|
||||
amount Float64
|
||||
) ENGINE = MergeTree ORDER BY id;
|
||||
|
||||
CREATE TABLE users (
|
||||
id UInt64,
|
||||
email String
|
||||
) ENGINE = MergeTree ORDER BY id;
|
||||
130
internal/endtoend/testdata/analyze_exec/clickhouse/stdout.json
vendored
Normal file
130
internal/endtoend/testdata/analyze_exec/clickhouse/stdout.json
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
[
|
||||
{
|
||||
"name": "CreateUser",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "uint64"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "email",
|
||||
"type": {
|
||||
"name": "string"
|
||||
},
|
||||
"table": "users"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CreateEvent",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "uint64"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"column": {
|
||||
"name": "tag",
|
||||
"type": {
|
||||
"name": "string",
|
||||
"nullable": true
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 4,
|
||||
"column": {
|
||||
"name": "amount",
|
||||
"type": {
|
||||
"name": "float64"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CreateEvents",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": [
|
||||
{
|
||||
"number": 1,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "uint64"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 2,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 3,
|
||||
"column": {
|
||||
"name": "id",
|
||||
"type": {
|
||||
"name": "uint64"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
},
|
||||
{
|
||||
"number": 4,
|
||||
"column": {
|
||||
"name": "name",
|
||||
"type": {
|
||||
"name": "string"
|
||||
},
|
||||
"table": "events"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "DropUsers",
|
||||
"cmd": ":exec",
|
||||
"columns": [],
|
||||
"params": []
|
||||
}
|
||||
]
|
||||
5
internal/endtoend/testdata/analyze_expressions/clickhouse/exec.json
vendored
Normal file
5
internal/endtoend/testdata/analyze_expressions/clickhouse/exec.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"command": "analyze",
|
||||
"args": ["--dialect", "clickhouse", "--schema", "schema.sql", "query.sql"],
|
||||
"contexts": ["base"]
|
||||
}
|
||||
2
internal/endtoend/testdata/analyze_expressions/clickhouse/fixture.sql
vendored
Normal file
2
internal/endtoend/testdata/analyze_expressions/clickhouse/fixture.sql
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
INSERT INTO events VALUES (1, 'signup', NULL, 9.5), (2, 'login', 'web', 0.5);
|
||||
INSERT INTO users VALUES (1, 'a@example.com');
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user