Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit74ecda5

Browse files
authored
feat: add SQLCEXPERIMENT environment variable for experimental features (#4228)
1 parentf6aee32 commit74ecda5

File tree

5 files changed

+324
-9
lines changed

5 files changed

+324
-9
lines changed

‎docs/reference/environment-variables.md‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
#Environment variables
22

3+
##SQLCEXPERIMENT
4+
5+
The`SQLCEXPERIMENT` variable controls experimental features within sqlc. It is
6+
a comma-separated list of experiment names. This is modeled after Go's
7+
[GOEXPERIMENT](https://pkg.go.dev/internal/goexperiment) environment variable.
8+
9+
Experiment names can be prefixed with`no` to explicitly disable them.
10+
11+
```
12+
SQLCEXPERIMENT=foo,bar # enable foo and bar experiments
13+
SQLCEXPERIMENT=nofoo # explicitly disable foo experiment
14+
SQLCEXPERIMENT=foo,nobar # enable foo, disable bar
15+
```
16+
17+
Currently, no experiments are defined. Experiments will be documented here as
18+
they are introduced.
19+
320
##SQLCCACHE
421

522
The`SQLCCACHE` environment variable dictates where`sqlc` will store cached

‎internal/cmd/cmd.go‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,21 +136,23 @@ var initCmd = &cobra.Command{
136136
}
137137

138138
typeEnvstruct {
139-
DryRunbool
140-
Debug opts.Debug
141-
Remotebool
142-
NoRemotebool
139+
DryRunbool
140+
Debug opts.Debug
141+
Experiment opts.Experiment
142+
Remotebool
143+
NoRemotebool
143144
}
144145

145146
funcParseEnv(c*cobra.Command)Env {
146147
dr:=c.Flag("dry-run")
147148
r:=c.Flag("remote")
148149
nr:=c.Flag("no-remote")
149150
returnEnv{
150-
DryRun:dr!=nil&&dr.Changed,
151-
Debug:opts.DebugFromEnv(),
152-
Remote:r!=nil&&r.Value.String()=="true",
153-
NoRemote:nr!=nil&&nr.Value.String()=="true",
151+
DryRun:dr!=nil&&dr.Changed,
152+
Debug:opts.DebugFromEnv(),
153+
Experiment:opts.ExperimentFromEnv(),
154+
Remote:r!=nil&&r.Value.String()=="true",
155+
NoRemote:nr!=nil&&nr.Value.String()=="true",
154156
}
155157
}
156158

‎internal/opts/experiment.go‎

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package opts
2+
3+
import (
4+
"os"
5+
"strings"
6+
)
7+
8+
// The SQLCEXPERIMENT variable controls experimental features within sqlc. It
9+
// is a comma-separated list of experiment names. Experiment names can be
10+
// prefixed with "no" to explicitly disable them.
11+
//
12+
// This is modeled after Go's GOEXPERIMENT environment variable. For more
13+
// information, see https://pkg.go.dev/internal/goexperiment
14+
//
15+
// Available experiments:
16+
//
17+
//(none currently defined - add experiments here as they are introduced)
18+
//
19+
// Example usage:
20+
//
21+
//SQLCEXPERIMENT=foo,bar # enable foo and bar experiments
22+
//SQLCEXPERIMENT=nofoo # explicitly disable foo experiment
23+
//SQLCEXPERIMENT=foo,nobar # enable foo, disable bar
24+
25+
// Experiment holds the state of all experimental features.
26+
// Add new experiments as boolean fields to this struct.
27+
typeExperimentstruct {
28+
// Add experimental feature flags here as they are introduced.
29+
// Example:
30+
// NewParser bool // Enable new SQL parser
31+
}
32+
33+
// ExperimentFromEnv returns an Experiment initialized from the SQLCEXPERIMENT
34+
// environment variable.
35+
funcExperimentFromEnv()Experiment {
36+
returnExperimentFromString(os.Getenv("SQLCEXPERIMENT"))
37+
}
38+
39+
// ExperimentFromString parses a comma-separated list of experiment names
40+
// and returns an Experiment with the appropriate flags set.
41+
//
42+
// Experiment names can be prefixed with "no" to explicitly disable them.
43+
// Unknown experiment names are silently ignored.
44+
funcExperimentFromString(valstring)Experiment {
45+
e:=Experiment{}
46+
ifval=="" {
47+
returne
48+
}
49+
50+
for_,name:=rangestrings.Split(val,",") {
51+
name=strings.TrimSpace(name)
52+
ifname=="" {
53+
continue
54+
}
55+
56+
// Check if this is a negation (noFoo)
57+
enabled:=true
58+
ifstrings.HasPrefix(strings.ToLower(name),"no")&&len(name)>2 {
59+
// Could be a negation, check if the rest is a valid experiment
60+
possibleExp:=name[2:]
61+
ifisKnownExperiment(possibleExp) {
62+
name=possibleExp
63+
enabled=false
64+
}
65+
// If not a known experiment, treat "no..." as a potential experiment name itself
66+
}
67+
68+
setExperiment(&e,name,enabled)
69+
}
70+
71+
returne
72+
}
73+
74+
// isKnownExperiment returns true if the given name (case-insensitive) is a
75+
// known experiment.
76+
funcisKnownExperiment(namestring)bool {
77+
switchstrings.ToLower(name) {
78+
// Add experiment names here as they are introduced.
79+
// Example:
80+
// case "newparser":
81+
// return true
82+
default:
83+
returnfalse
84+
}
85+
}
86+
87+
// setExperiment sets the experiment flag with the given name to the given value.
88+
funcsetExperiment(e*Experiment,namestring,enabledbool) {
89+
switchstrings.ToLower(name) {
90+
// Add experiment cases here as they are introduced.
91+
// Example:
92+
// case "newparser":
93+
// e.NewParser = enabled
94+
}
95+
}
96+
97+
// Enabled returns a slice of all enabled experiment names.
98+
func (eExperiment)Enabled() []string {
99+
varenabled []string
100+
// Add enabled experiments here as they are introduced.
101+
// Example:
102+
// if e.NewParser {
103+
// enabled = append(enabled, "newparser")
104+
// }
105+
returnenabled
106+
}
107+
108+
// String returns a comma-separated list of enabled experiments.
109+
func (eExperiment)String()string {
110+
returnstrings.Join(e.Enabled(),",")
111+
}

‎internal/opts/experiment_test.go‎

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package opts
2+
3+
import"testing"
4+
5+
funcTestExperimentFromString(t*testing.T) {
6+
tests:= []struct {
7+
namestring
8+
inputstring
9+
wantExperiment
10+
}{
11+
{
12+
name:"empty string",
13+
input:"",
14+
want:Experiment{},
15+
},
16+
{
17+
name:"whitespace only",
18+
input:" ",
19+
want:Experiment{},
20+
},
21+
{
22+
name:"unknown experiment",
23+
input:"unknownexperiment",
24+
want:Experiment{},
25+
},
26+
{
27+
name:"multiple unknown experiments",
28+
input:"foo,bar,baz",
29+
want:Experiment{},
30+
},
31+
{
32+
name:"unknown with no prefix",
33+
input:"nounknown",
34+
want:Experiment{},
35+
},
36+
{
37+
name:"whitespace around experiments",
38+
input:" foo , bar , baz ",
39+
want:Experiment{},
40+
},
41+
{
42+
name:"empty items in list",
43+
input:"foo,,bar",
44+
want:Experiment{},
45+
},
46+
// Add tests for specific experiments as they are introduced.
47+
// Example:
48+
// {
49+
// name: "enable newparser",
50+
// input: "newparser",
51+
// want: Experiment{NewParser: true},
52+
// },
53+
// {
54+
// name: "disable newparser",
55+
// input: "nonewparser",
56+
// want: Experiment{NewParser: false},
57+
// },
58+
// {
59+
// name: "enable then disable",
60+
// input: "newparser,nonewparser",
61+
// want: Experiment{NewParser: false},
62+
// },
63+
// {
64+
// name: "case insensitive",
65+
// input: "NewParser,NONEWPARSER",
66+
// want: Experiment{NewParser: false},
67+
// },
68+
}
69+
70+
for_,tt:=rangetests {
71+
t.Run(tt.name,func(t*testing.T) {
72+
got:=ExperimentFromString(tt.input)
73+
ifgot!=tt.want {
74+
t.Errorf("ExperimentFromString(%q) = %+v, want %+v",tt.input,got,tt.want)
75+
}
76+
})
77+
}
78+
}
79+
80+
funcTestExperimentEnabled(t*testing.T) {
81+
tests:= []struct {
82+
namestring
83+
expExperiment
84+
want []string
85+
}{
86+
{
87+
name:"no experiments enabled",
88+
exp:Experiment{},
89+
want:nil,
90+
},
91+
// Add tests for specific experiments as they are introduced.
92+
// Example:
93+
// {
94+
// name: "newparser enabled",
95+
// exp: Experiment{NewParser: true},
96+
// want: []string{"newparser"},
97+
// },
98+
}
99+
100+
for_,tt:=rangetests {
101+
t.Run(tt.name,func(t*testing.T) {
102+
got:=tt.exp.Enabled()
103+
iflen(got)!=len(tt.want) {
104+
t.Errorf("Experiment.Enabled() = %v, want %v",got,tt.want)
105+
return
106+
}
107+
fori:=rangegot {
108+
ifgot[i]!=tt.want[i] {
109+
t.Errorf("Experiment.Enabled()[%d] = %q, want %q",i,got[i],tt.want[i])
110+
}
111+
}
112+
})
113+
}
114+
}
115+
116+
funcTestExperimentString(t*testing.T) {
117+
tests:= []struct {
118+
namestring
119+
expExperiment
120+
wantstring
121+
}{
122+
{
123+
name:"no experiments",
124+
exp:Experiment{},
125+
want:"",
126+
},
127+
// Add tests for specific experiments as they are introduced.
128+
// Example:
129+
// {
130+
// name: "newparser enabled",
131+
// exp: Experiment{NewParser: true},
132+
// want: "newparser",
133+
// },
134+
}
135+
136+
for_,tt:=rangetests {
137+
t.Run(tt.name,func(t*testing.T) {
138+
got:=tt.exp.String()
139+
ifgot!=tt.want {
140+
t.Errorf("Experiment.String() = %q, want %q",got,tt.want)
141+
}
142+
})
143+
}
144+
}
145+
146+
funcTestIsKnownExperiment(t*testing.T) {
147+
tests:= []struct {
148+
namestring
149+
inputstring
150+
wantbool
151+
}{
152+
{
153+
name:"unknown experiment",
154+
input:"unknown",
155+
want:false,
156+
},
157+
{
158+
name:"empty string",
159+
input:"",
160+
want:false,
161+
},
162+
// Add tests for specific experiments as they are introduced.
163+
// Example:
164+
// {
165+
// name: "newparser lowercase",
166+
// input: "newparser",
167+
// want: true,
168+
// },
169+
// {
170+
// name: "newparser mixed case",
171+
// input: "NewParser",
172+
// want: true,
173+
// },
174+
}
175+
176+
for_,tt:=rangetests {
177+
t.Run(tt.name,func(t*testing.T) {
178+
got:=isKnownExperiment(tt.input)
179+
ifgot!=tt.want {
180+
t.Errorf("isKnownExperiment(%q) = %v, want %v",tt.input,got,tt.want)
181+
}
182+
})
183+
}
184+
}

‎internal/opts/parser.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package opts
22

33
typeParserstruct {
4-
DebugDebug
4+
DebugDebug
5+
ExperimentExperiment
56
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp