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:
199
internal/compiler/engine.go
Normal file
199
internal/compiler/engine.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/sqlc-dev/sqlc/internal/analyzer"
|
||||
"github.com/sqlc-dev/sqlc/internal/config"
|
||||
"github.com/sqlc-dev/sqlc/internal/core"
|
||||
"github.com/sqlc-dev/sqlc/internal/dbmanager"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/clickhouse"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/dolphin"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/duckdb"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/googlesql"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/mssql"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/postgresql"
|
||||
pganalyze "github.com/sqlc-dev/sqlc/internal/engine/postgresql/analyzer"
|
||||
"github.com/sqlc-dev/sqlc/internal/engine/sqlite"
|
||||
sqliteanalyze "github.com/sqlc-dev/sqlc/internal/engine/sqlite/analyzer"
|
||||
"github.com/sqlc-dev/sqlc/internal/opts"
|
||||
"github.com/sqlc-dev/sqlc/internal/sql/catalog"
|
||||
)
|
||||
|
||||
type Compiler struct {
|
||||
conf config.SQL
|
||||
combo config.CombinedSettings
|
||||
catalog *catalog.Catalog
|
||||
parser Parser
|
||||
result *Result
|
||||
analyzer analyzer.Analyzer
|
||||
client dbmanager.Client
|
||||
selector selector
|
||||
|
||||
coreCatalog *core.Catalog
|
||||
|
||||
// coreAnalysis routes every engine through the core catalog and analyzer,
|
||||
// and coreDialect seeds the catalog it does so with. The catalog itself is
|
||||
// not built until the schema is loaded, because the two are cached
|
||||
// together.
|
||||
coreAnalysis bool
|
||||
coreDialect core.Option
|
||||
|
||||
// newParser builds a parser for the configured engine, and is set for
|
||||
// every engine either path supports. The core path analyzes statements
|
||||
// concurrently, and a parser holds enough state that two goroutines cannot
|
||||
// share one, so a goroutine that has to parse something of its own — the
|
||||
// query text it just rewrote — builds its own rather than taking c.parser.
|
||||
newParser func() Parser
|
||||
|
||||
schema []string
|
||||
}
|
||||
|
||||
// Option configures a Compiler.
|
||||
type Option func(*Compiler)
|
||||
|
||||
// WithCoreAnalysis analyzes queries with the core catalog and analyzer rather
|
||||
// than each engine's own analysis path. ClickHouse and GoogleSQL always do;
|
||||
// this opts the remaining engines in.
|
||||
func WithCoreAnalysis() Option {
|
||||
return func(c *Compiler) { c.coreAnalysis = true }
|
||||
}
|
||||
|
||||
func NewCompiler(conf config.SQL, combo config.CombinedSettings, parserOpts opts.Parser, options ...Option) (*Compiler, error) {
|
||||
c := &Compiler{conf: conf, combo: combo}
|
||||
for _, o := range options {
|
||||
o(c)
|
||||
}
|
||||
|
||||
// ClickHouse, GoogleSQL, SQL Server and DuckDB have no legacy analysis
|
||||
// path to fall back to.
|
||||
switch conf.Engine {
|
||||
case config.EngineClickHouse, config.EngineGoogleSQL, config.EngineMSSQL, config.EngineDuckDB:
|
||||
c.coreAnalysis = true
|
||||
}
|
||||
if c.coreAnalysis {
|
||||
if err := c.initCore(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
if conf.Database != nil && conf.Database.Managed {
|
||||
client := dbmanager.NewClient(combo.Global.Servers)
|
||||
c.client = client
|
||||
}
|
||||
|
||||
switch conf.Engine {
|
||||
case config.EngineSQLite:
|
||||
c.newParser = func() Parser { return sqlite.NewParser() }
|
||||
c.catalog = sqlite.NewCatalog()
|
||||
c.selector = newSQLiteSelector()
|
||||
|
||||
if conf.Database != nil {
|
||||
if conf.Analyzer.Database == nil || *conf.Analyzer.Database {
|
||||
c.analyzer = analyzer.Cached(
|
||||
sqliteanalyze.New(*conf.Database),
|
||||
combo.Global,
|
||||
*conf.Database,
|
||||
)
|
||||
}
|
||||
}
|
||||
case config.EngineMySQL:
|
||||
c.newParser = func() Parser { return dolphin.NewParser() }
|
||||
c.catalog = dolphin.NewCatalog()
|
||||
c.selector = newDefaultSelector()
|
||||
case config.EnginePostgreSQL:
|
||||
c.newParser = func() Parser { return postgresql.NewParser() }
|
||||
c.catalog = postgresql.NewCatalog()
|
||||
c.selector = newDefaultSelector()
|
||||
|
||||
if conf.Database != nil {
|
||||
if conf.Analyzer.Database == nil || *conf.Analyzer.Database {
|
||||
c.analyzer = analyzer.Cached(
|
||||
pganalyze.New(c.client, *conf.Database),
|
||||
combo.Global,
|
||||
*conf.Database,
|
||||
)
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown engine: %s", conf.Engine)
|
||||
}
|
||||
c.parser = c.newParser()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// initCore wires up the engine's parser and a core catalog seeded with its
|
||||
// dialect. No legacy catalog and no analyzer connection are involved.
|
||||
func (c *Compiler) initCore() error {
|
||||
var dialect core.Option
|
||||
switch c.conf.Engine {
|
||||
case config.EngineSQLite:
|
||||
c.newParser = func() Parser { return sqlite.NewParser() }
|
||||
c.selector = newSQLiteSelector()
|
||||
dialect = sqlite.Dialect()
|
||||
case config.EngineMySQL:
|
||||
c.newParser = func() Parser { return dolphin.NewParser() }
|
||||
c.selector = newDefaultSelector()
|
||||
dialect = dolphin.Dialect()
|
||||
case config.EnginePostgreSQL:
|
||||
c.newParser = func() Parser { return postgresql.NewParser() }
|
||||
c.selector = newDefaultSelector()
|
||||
dialect = postgresql.Dialect()
|
||||
case config.EngineClickHouse:
|
||||
c.newParser = func() Parser { return clickhouse.NewParser() }
|
||||
c.selector = newDefaultSelector()
|
||||
dialect = clickhouse.Dialect()
|
||||
case config.EngineGoogleSQL:
|
||||
c.newParser = func() Parser { return googlesql.NewParser() }
|
||||
c.selector = newDefaultSelector()
|
||||
dialect = googlesql.Dialect()
|
||||
case config.EngineMSSQL:
|
||||
c.newParser = func() Parser { return mssql.NewParser() }
|
||||
c.selector = newDefaultSelector()
|
||||
dialect = mssql.Dialect()
|
||||
case config.EngineDuckDB:
|
||||
c.newParser = func() Parser { return duckdb.NewParser() }
|
||||
c.selector = newDefaultSelector()
|
||||
dialect = duckdb.Dialect()
|
||||
default:
|
||||
return fmt.Errorf("unknown engine: %s", c.conf.Engine)
|
||||
}
|
||||
c.parser = c.newParser()
|
||||
c.coreDialect = dialect
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Compiler) Catalog() *catalog.Catalog {
|
||||
return c.catalog
|
||||
}
|
||||
|
||||
func (c *Compiler) ParseCatalog(schema []string) error {
|
||||
return c.parseCatalog(schema)
|
||||
}
|
||||
|
||||
func (c *Compiler) ParseQueries(queries []string, o opts.Parser) error {
|
||||
r, err := c.parseQueries(o)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.result = r
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Compiler) Result() *Result {
|
||||
return c.result
|
||||
}
|
||||
|
||||
func (c *Compiler) Close(ctx context.Context) {
|
||||
if c.analyzer != nil {
|
||||
c.analyzer.Close(ctx)
|
||||
}
|
||||
if c.client != nil {
|
||||
c.client.Close(ctx)
|
||||
}
|
||||
if c.coreCatalog != nil {
|
||||
c.coreCatalog.Close()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user