From b8042becc85c008cf522dcab2b6f409d4a860b85 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 30 Oct 2025 16:46:16 +0800 Subject: [PATCH 1/5] feat: add configuration for plugin to run go package --- internal/cmd/generate.go | 1 + internal/config/config.go | 1 + internal/ext/process/gen.go | 25 ++++++++++++++++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go index 00e8871c7e..de8342c4d9 100644 --- a/internal/cmd/generate.go +++ b/internal/cmd/generate.go @@ -349,6 +349,7 @@ func codegen(ctx context.Context, combo config.CombinedSettings, sql OutputPair, switch { case plug.Process != nil: handler = &process.Runner{ + GoPkg: plug.Process.GoPkg, Cmd: plug.Process.Cmd, Env: plug.Env, Format: plug.Process.Format, diff --git a/internal/config/config.go b/internal/config/config.go index 0ff805fccd..c9a39703ce 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -89,6 +89,7 @@ type Plugin struct { Name string `json:"name" yaml:"name"` Env []string `json:"env" yaml:"env"` Process *struct { + GoPkg string `json:"go_package" yaml:"go_package"` Cmd string `json:"cmd" yaml:"cmd"` Format string `json:"format" yaml:"format"` } `json:"process" yaml:"process"` diff --git a/internal/ext/process/gen.go b/internal/ext/process/gen.go index b5720dbc33..d232e7e1db 100644 --- a/internal/ext/process/gen.go +++ b/internal/ext/process/gen.go @@ -19,6 +19,7 @@ import ( ) type Runner struct { + GoPkg string Cmd string Format string Env []string @@ -53,13 +54,27 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any, return fmt.Errorf("unknown plugin format: %s", r.Format) } - // Check if the output plugin exists - path, err := exec.LookPath(r.Cmd) - if err != nil { - return fmt.Errorf("process: %s not found", r.Cmd) + var cmd *exec.Cmd + switch { + case r.Cmd != "" && r.GoPkg == "": + // Check if the output plugin exists + path, err := exec.LookPath(r.Cmd) + if err != nil { + return fmt.Errorf("process: %s not found", r.Cmd) + } + cmd = exec.CommandContext(ctx, path, method) + case r.Cmd == "" && r.GoPkg != "": + // Check if the go binary exists + path, err := exec.LookPath("go") + if err != nil { + return fmt.Errorf("go binary required to run go package %s", r.GoPkg) + } + cmd = exec.CommandContext(ctx, path, method) + cmd.Args = []string{"run", r.GoPkg} + default: + return fmt.Errorf("cmd and go_package cannot both be empty for process plugin") } - cmd := exec.CommandContext(ctx, path, method) cmd.Stdin = bytes.NewReader(stdin) cmd.Env = []string{ fmt.Sprintf("SQLC_VERSION=%s", info.Version), From 1d17f5af7dc588a8081d81b174ff87f79b402a6c Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 30 Oct 2025 16:50:34 +0800 Subject: [PATCH 2/5] check both fields --- internal/ext/process/gen.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/ext/process/gen.go b/internal/ext/process/gen.go index d232e7e1db..c0d3b3d0d7 100644 --- a/internal/ext/process/gen.go +++ b/internal/ext/process/gen.go @@ -71,6 +71,8 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any, } cmd = exec.CommandContext(ctx, path, method) cmd.Args = []string{"run", r.GoPkg} + case r.Cmd != "" && r.GoPkg != "": + return fmt.Errorf("only one of cmd or go_package is allowed") default: return fmt.Errorf("cmd and go_package cannot both be empty for process plugin") } From 6947d668c1ea8b4387f38bd3cc3659a24deb593d Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 30 Oct 2025 16:59:26 +0800 Subject: [PATCH 3/5] fix config check --- internal/config/config.go | 3 ++- internal/config/v_two.go | 7 +++++-- internal/ext/process/gen.go | 8 ++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/internal/config/config.go b/internal/config/config.go index c9a39703ce..57ce814a8d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -160,7 +160,8 @@ var ErrPluginExists = errors.New("a plugin with that name already exists") var ErrPluginNotFound = errors.New("no plugin found") var ErrPluginNoType = errors.New("plugin: field `process` or `wasm` required") var ErrPluginBothTypes = errors.New("plugin: `process` and `wasm` cannot both be defined") -var ErrPluginProcessNoCmd = errors.New("plugin: missing process command") +var ErrPluginProcessTooManyCmd = errors.New("plugin: only one of `cmd` or `go_package` is allowed for process plugin") +var ErrPluginProcessNoCmd = errors.New("plugin: missing `cmd` or `go_package` for process plugin") var ErrInvalidDatabase = errors.New("database must be managed or have a non-empty URI") var ErrManagedDatabaseNoProject = errors.New(`managed databases require a cloud project diff --git a/internal/config/v_two.go b/internal/config/v_two.go index 0fe22ffa2c..a83de1d7d1 100644 --- a/internal/config/v_two.go +++ b/internal/config/v_two.go @@ -48,8 +48,11 @@ func v2ParseConfig(rd io.Reader) (Config, error) { if conf.Plugins[i].Process != nil && conf.Plugins[i].WASM != nil { return conf, ErrPluginBothTypes } - if conf.Plugins[i].Process != nil { - if conf.Plugins[i].Process.Cmd == "" { + if r := conf.Plugins[i].Process; r != nil { + switch { + case r.Cmd != "" && r.GoPkg != "": + return conf, ErrPluginProcessTooManyCmd + case r.Cmd == "" && r.GoPkg == "": return conf, ErrPluginProcessNoCmd } } diff --git a/internal/ext/process/gen.go b/internal/ext/process/gen.go index c0d3b3d0d7..b8dadbddd5 100644 --- a/internal/ext/process/gen.go +++ b/internal/ext/process/gen.go @@ -56,14 +56,14 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any, var cmd *exec.Cmd switch { - case r.Cmd != "" && r.GoPkg == "": + case r.Cmd != "": // Check if the output plugin exists path, err := exec.LookPath(r.Cmd) if err != nil { return fmt.Errorf("process: %s not found", r.Cmd) } cmd = exec.CommandContext(ctx, path, method) - case r.Cmd == "" && r.GoPkg != "": + case r.GoPkg != "": // Check if the go binary exists path, err := exec.LookPath("go") if err != nil { @@ -71,10 +71,6 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any, } cmd = exec.CommandContext(ctx, path, method) cmd.Args = []string{"run", r.GoPkg} - case r.Cmd != "" && r.GoPkg != "": - return fmt.Errorf("only one of cmd or go_package is allowed") - default: - return fmt.Errorf("cmd and go_package cannot both be empty for process plugin") } cmd.Stdin = bytes.NewReader(stdin) From 39de25e05a6b5e4c94f5bae58376e7de5bbf081c Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 30 Oct 2025 17:02:21 +0800 Subject: [PATCH 4/5] last fix ever --- internal/ext/process/gen.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ext/process/gen.go b/internal/ext/process/gen.go index b8dadbddd5..34b5f90b03 100644 --- a/internal/ext/process/gen.go +++ b/internal/ext/process/gen.go @@ -70,7 +70,7 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any, return fmt.Errorf("go binary required to run go package %s", r.GoPkg) } cmd = exec.CommandContext(ctx, path, method) - cmd.Args = []string{"run", r.GoPkg} + cmd.Args = []string{"go", "run", r.GoPkg} } cmd.Stdin = bytes.NewReader(stdin) From 9a2aa651c81628e015764651b6ae8b5f5bbe59a3 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 30 Oct 2025 17:34:16 +0800 Subject: [PATCH 5/5] require golang envs --- internal/ext/process/gen.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/internal/ext/process/gen.go b/internal/ext/process/gen.go index 34b5f90b03..9507cfb9b2 100644 --- a/internal/ext/process/gen.go +++ b/internal/ext/process/gen.go @@ -71,6 +71,20 @@ func (r *Runner) Invoke(ctx context.Context, method string, args any, reply any, } cmd = exec.CommandContext(ctx, path, method) cmd.Args = []string{"go", "run", r.GoPkg} + r.Env = append(r.Env, []string{ + "GO111MODULE", + "GOROOT", + "GOPATH", + "GOPROXY", + "GOPRIVATE", + "GONOPROXY", + "GONOSUMDB", + "GOMODCACHE", + "GOFLAGS", + "GOCACHE", + "GOENV", + "HOME", + }...) } cmd.Stdin = bytes.NewReader(stdin)