Skip to content

Commit 586dfb2

Browse files
authored
goldeneye: generate the SQLite dialect from the official sqlite3 shell (#4606)
1 parent 8f23752 commit 586dfb2

30 files changed

Lines changed: 1814 additions & 161 deletions

File tree

.github/workflows/gen.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ jobs:
2424
check-latest: true
2525
- run: go run ./cmd/goldeneye install clickhouse
2626
working-directory: internal/goldeneye
27+
- run: go run ./cmd/goldeneye install sqlite
28+
working-directory: internal/goldeneye
2729
- run: go run ./cmd/goldeneye generate
2830
working-directory: internal/goldeneye
2931
env:

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ is not available skip.
153153
```bash
154154
cd internal/goldeneye
155155
go run ./cmd/goldeneye install clickhouse # download the pinned clickhouse binary once
156+
go run ./cmd/goldeneye install sqlite # build the pinned sqlite3 shells once; needs a C compiler
156157
POSTGRESQL_SERVER_URI="postgres://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable" go test ./...
157158
go run ./cmd/goldeneye generate postgresql # rewrite the files after a change
158159
```

internal/core/schema/schema.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,13 @@ func applyCreateTable(cat *core.Catalog, stmt *ast.CreateTableStmt) error {
133133
if stmt.Name == nil {
134134
return fmt.Errorf("create table with nil name")
135135
}
136+
// A virtual table's module is the dialect's word for the extension it
137+
// needs, the way CREATE EXTENSION is PostgreSQL's.
138+
if stmt.Using != "" {
139+
if err := cat.LoadExtension(stmt.Using); err != nil {
140+
return err
141+
}
142+
}
136143
nsOID, err := resolveOrCreateNamespace(cat, stmt.Name.Schema)
137144
if err != nil {
138145
return err

internal/core/seed/extension.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,12 @@ import (
99
"github.com/sqlc-dev/sqlc/internal/core"
1010
)
1111

12-
// applyExtension applies the named extension's directory to a catalog that
13-
// has already been seeded. Unlike the dialect's own seed, an extension lands
14-
// in a catalog full of types, so everything it names is resolved against what
15-
// is there before being created.
16-
func applyExtension(cat *core.Catalog, fsys fs.FS, name string) error {
17-
dir := path.Join(ExtensionsDir, name)
18-
if _, err := fs.Stat(fsys, dir); err != nil {
19-
// An extension sqlc has no data for adds nothing, the way the legacy
20-
// catalog has always treated one.
21-
return nil
22-
}
12+
// applyExtension applies the extension directory dir, relative to the
13+
// dialect, to a catalog that has already been seeded. Unlike the dialect's
14+
// own seed, an extension lands in a catalog full of types, so everything it
15+
// names is resolved against what is there before being created.
16+
func applyExtension(cat *core.Catalog, fsys fs.FS, dir string) error {
17+
name := path.Base(dir)
2318
sub, err := fs.Sub(fsys, dir)
2419
if err != nil {
2520
return fmt.Errorf("seed: extension %s: %w", name, err)

internal/core/seed/seed.go

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
//
1919
// A dialect may also hold an extensions/ directory with one directory per
2020
// extension, each a smaller bundle of the same files, applied when a schema
21-
// says CREATE EXTENSION.
21+
// says CREATE EXTENSION — or, for a dialect whose settings map virtual table
22+
// modules to extensions, CREATE VIRTUAL TABLE ... USING.
2223
package seed
2324

2425
import (
@@ -28,6 +29,7 @@ import (
2829
"fmt"
2930
"io"
3031
"io/fs"
32+
"path"
3133
"slices"
3234
"strings"
3335

@@ -78,6 +80,15 @@ type Settings struct {
7880
// same kind of value resolves. "*" makes every seeded type implicitly
7981
// castable to every other, for dialects that compare across categories.
8082
CastCategories string `json:"cast_categories,omitempty"`
83+
84+
// Modules names the extension a virtual table module belongs to, for a
85+
// dialect whose schemas say CREATE VIRTUAL TABLE ... USING rather than
86+
// CREATE EXTENSION: SQLite's fts5 module comes with the functions its
87+
// enable_fts5 compile option adds.
88+
Modules map[string]string `json:"modules,omitempty"`
89+
90+
// fsys is the dialect directory the settings were read from.
91+
fsys fs.FS
8192
}
8293

8394
// Type is a type the dialect defines. Aliases are spellings of the same type
@@ -155,21 +166,60 @@ func Dialect(fsys fs.FS, dir string) core.Option {
155166
if err != nil {
156167
return fmt.Errorf("seed: %s: %w", dir, err)
157168
}
158-
if err := apply(cat, sub); err != nil {
169+
settings, err := loadSettings(sub)
170+
if err != nil {
171+
return err
172+
}
173+
if err := apply(cat, sub, settings); err != nil {
159174
return err
160175
}
161176
cat.SetExtensionLoader(func(name string) error {
162-
return applyExtension(cat, sub, name)
177+
dir, ok := settings.extensionDir(name)
178+
if !ok {
179+
// An extension sqlc has no data for adds nothing, the way
180+
// the legacy catalog has always treated one.
181+
return nil
182+
}
183+
return applyExtension(cat, sub, dir)
163184
})
164185
return nil
165186
})
166187
}
167188

168-
func apply(cat *core.Catalog, fsys fs.FS) error {
169-
settings, err := loadSettings(fsys)
189+
// ExtensionDir resolves what a schema named — an extension, or a virtual
190+
// table module the dialect's settings map to one — to the extension's
191+
// directory under dir, reporting whether the dialect has data for it.
192+
func ExtensionDir(fsys fs.FS, dir, name string) (string, bool) {
193+
sub, err := fs.Sub(fsys, dir)
170194
if err != nil {
171-
return err
195+
return "", false
172196
}
197+
settings, err := loadSettings(sub)
198+
if err != nil {
199+
return "", false
200+
}
201+
rel, ok := settings.extensionDir(name)
202+
if !ok {
203+
return "", false
204+
}
205+
return path.Join(dir, rel), true
206+
}
207+
208+
// extensionDir is the directory of the extension a name refers to,
209+
// relative to the dialect, if the dialect ships one.
210+
func (s Settings) extensionDir(name string) (string, bool) {
211+
if ext, ok := s.Modules[strings.ToLower(name)]; ok {
212+
name = ext
213+
}
214+
dir := path.Join(ExtensionsDir, name)
215+
if _, err := fs.Stat(s.fsys, dir); err != nil {
216+
return "", false
217+
}
218+
return dir, true
219+
}
220+
221+
func apply(cat *core.Catalog, fsys fs.FS, settings Settings) error {
222+
var err error
173223
b := &builder{
174224
cat: cat,
175225
settings: settings,
@@ -222,6 +272,7 @@ func loadSettings(fsys fs.FS) (Settings, error) {
222272
if settings.Dialect == "" {
223273
return Settings{}, fmt.Errorf("seed: %s: dialect has no name", SettingsFile)
224274
}
275+
settings.fsys = fsys
225276
return settings, nil
226277
}
227278

internal/endtoend/testdata/builtins/sqlite/go/aggfunc.sql.go

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/builtins/sqlite/go/mathfunc.sql.go

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/builtins/sqlite/go/scalarfunc.sql.go

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/table_function/sqlite/go/query.sql.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/engine/sqlite/catalog.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ func NewCatalog() *catalog.Catalog {
99
Schemas: []*catalog.Schema{
1010
defaultSchema(def),
1111
},
12-
Extensions: map[string]struct{}{},
12+
LoadExtension: loadExtension,
13+
Extensions: map[string]struct{}{},
1314
}
1415
}

0 commit comments

Comments
 (0)