Skip to content

Commit 0f81f5d

Browse files
committed
merge files
1 parent 85475e2 commit 0f81f5d

File tree

2 files changed

+69
-83
lines changed

2 files changed

+69
-83
lines changed

internal/cmd/engine_plugin_runner.go

Lines changed: 0 additions & 79 deletions
This file was deleted.
Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
package cmd
1+
// This file runs a database-engine plugin as an external process (parse RPC over stdin/stdout).
2+
// It is used only by the plugin-engine generate path (runPluginQuerySet). Vet does not support plugin engines.
23

3-
// This file implements the plugin-**engine** path only (runPluginQuerySet).
4-
// When engine is not builtin, generate calls runPluginQuerySet: schema+query → engine plugin ParseRequest → compiler.Result → ProcessResult/codegen.
5-
// Codegen plugins are handled in generate.go/shim; this file is only for external database engines.
4+
package cmd
65

76
import (
7+
"bytes"
88
"context"
9+
"errors"
910
"fmt"
1011
"os"
12+
"os/exec"
1113
"path/filepath"
1214
"strings"
1315

@@ -18,9 +20,72 @@ import (
1820
"github.com/sqlc-dev/sqlc/internal/source"
1921
"github.com/sqlc-dev/sqlc/internal/sql/catalog"
2022
"github.com/sqlc-dev/sqlc/internal/sql/sqlpath"
23+
"google.golang.org/protobuf/proto"
24+
25+
"github.com/sqlc-dev/sqlc/internal/info"
2126
pb "github.com/sqlc-dev/sqlc/pkg/engine"
2227
)
2328

29+
// engineProcessRunner runs an engine plugin as an external process.
30+
type engineProcessRunner struct {
31+
Cmd string
32+
Dir string // Working directory for the plugin (config file directory)
33+
Env []string
34+
}
35+
36+
func newEngineProcessRunner(cmd, dir string, env []string) *engineProcessRunner {
37+
return &engineProcessRunner{Cmd: cmd, Dir: dir, Env: env}
38+
}
39+
40+
func (r *engineProcessRunner) invoke(ctx context.Context, method string, req, resp proto.Message) error {
41+
stdin, err := proto.Marshal(req)
42+
if err != nil {
43+
return fmt.Errorf("failed to encode request: %w", err)
44+
}
45+
46+
cmdParts := strings.Fields(r.Cmd)
47+
if len(cmdParts) == 0 {
48+
return fmt.Errorf("engine plugin not found: %s\n\nMake sure the plugin is installed and available in PATH.\nInstall with: go install <plugin-module>@latest", r.Cmd)
49+
}
50+
51+
path, err := exec.LookPath(cmdParts[0])
52+
if err != nil {
53+
return fmt.Errorf("engine plugin not found: %s\n\nMake sure the plugin is installed and available in PATH.\nInstall with: go install <plugin-module>@latest", r.Cmd)
54+
}
55+
56+
args := append(cmdParts[1:], method)
57+
cmd := exec.CommandContext(ctx, path, args...)
58+
cmd.Stdin = bytes.NewReader(stdin)
59+
if r.Dir != "" {
60+
cmd.Dir = r.Dir
61+
}
62+
cmd.Env = append(os.Environ(), fmt.Sprintf("SQLC_VERSION=%s", info.Version))
63+
64+
out, err := cmd.Output()
65+
if err != nil {
66+
stderr := err.Error()
67+
var exit *exec.ExitError
68+
if errors.As(err, &exit) {
69+
stderr = string(exit.Stderr)
70+
}
71+
return fmt.Errorf("engine plugin error: %s", stderr)
72+
}
73+
74+
if err := proto.Unmarshal(out, resp); err != nil {
75+
return fmt.Errorf("failed to decode response: %w", err)
76+
}
77+
return nil
78+
}
79+
80+
// parseRequest invokes the plugin's Parse RPC. Used by runPluginQuerySet.
81+
func (r *engineProcessRunner) parseRequest(ctx context.Context, req *pb.ParseRequest) (*pb.ParseResponse, error) {
82+
resp := &pb.ParseResponse{}
83+
if err := r.invoke(ctx, "parse", req, resp); err != nil {
84+
return nil, err
85+
}
86+
return resp, nil
87+
}
88+
2489
// defaultCommentSyntax is used when parsing query names from plugin-engine query files.
2590
var defaultCommentSyntax = metadata.CommentSyntax(source.CommentSyntax{Dash: true, SlashStar: true, Hash: false})
2691

0 commit comments

Comments
 (0)