Skip to content

Commit 751e859

Browse files
Ajit Pratap Singhclaude
authored andcommitted
fix(mariadb): address code review — CycleOption enum, CACHE validation, structured errors
- Replace Cycle bool + NoCycle bool with CycleOption enum to prevent invalid state where both could be true simultaneously - Add validation in parseSequenceOptions for contradictory CACHE/NOCACHE - Replace fmt.Errorf with p.expectedError() for consistent error style Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 64bf553 commit 751e859

5 files changed

Lines changed: 28 additions & 12 deletions

File tree

pkg/sql/ast/ast.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,18 @@ func (r ReplaceStatement) Children() []Node {
18411841

18421842
// ── MariaDB SEQUENCE DDL (10.3+) ───────────────────────────────────────────
18431843

1844+
// CycleOption represents the CYCLE behavior for a sequence.
1845+
type CycleOption int
1846+
1847+
const (
1848+
// CycleUnspecified means no CYCLE or NOCYCLE clause was given (database default applies).
1849+
CycleUnspecified CycleOption = iota
1850+
// CycleBehavior means CYCLE — sequence wraps around when it reaches min/max.
1851+
CycleBehavior
1852+
// NoCycleBehavior means NOCYCLE / NO CYCLE — sequence errors on overflow.
1853+
NoCycleBehavior
1854+
)
1855+
18441856
// SequenceOptions holds configuration for CREATE SEQUENCE and ALTER SEQUENCE.
18451857
// Fields are pointers so that unspecified options are distinguishable from zero values.
18461858
type SequenceOptions struct {
@@ -1849,8 +1861,7 @@ type SequenceOptions struct {
18491861
MinValue *LiteralValue // MINVALUE n or nil when NO MINVALUE
18501862
MaxValue *LiteralValue // MAXVALUE n or nil when NO MAXVALUE
18511863
Cache *LiteralValue // CACHE n or nil when NO CACHE / NOCACHE
1852-
Cycle bool // CYCLE
1853-
NoCycle bool // NO CYCLE / NOCYCLE (explicit; default is NO CYCLE)
1864+
CycleMode CycleOption // CYCLE / NOCYCLE / NO CYCLE (CycleUnspecified if not specified)
18541865
NoCache bool // NOCACHE (explicit; Cache=nil alone is ambiguous)
18551866
Restart bool // bare RESTART (reset to start value)
18561867
RestartWith *LiteralValue // RESTART WITH n (explicit restart value)

pkg/sql/ast/ast_sequence_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func TestCreateSequenceStatement_ToSQL(t *testing.T) {
4646
MinValue: &ast.LiteralValue{Value: "1"},
4747
MaxValue: &ast.LiteralValue{Value: "9999"},
4848
Cache: &ast.LiteralValue{Value: "100"},
49-
Cycle: true,
49+
CycleMode: ast.CycleBehavior,
5050
},
5151
},
5252
want: "CREATE SEQUENCE s START WITH 1 INCREMENT BY 1 MINVALUE 1 MAXVALUE 9999 CACHE 100 CYCLE",
@@ -55,7 +55,7 @@ func TestCreateSequenceStatement_ToSQL(t *testing.T) {
5555
name: "nocycle",
5656
stmt: &ast.CreateSequenceStatement{
5757
Name: &ast.Identifier{Name: "s"},
58-
Options: ast.SequenceOptions{NoCycle: true},
58+
Options: ast.SequenceOptions{CycleMode: ast.NoCycleBehavior},
5959
},
6060
want: "CREATE SEQUENCE s NOCYCLE",
6161
},

pkg/sql/ast/sql.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,9 +1672,10 @@ func writeSequenceOptions(b *strings.Builder, opts SequenceOptions) {
16721672
} else if opts.NoCache {
16731673
b.WriteString(" NOCACHE")
16741674
}
1675-
if opts.Cycle {
1675+
switch opts.CycleMode {
1676+
case CycleBehavior:
16761677
b.WriteString(" CYCLE")
1677-
} else if opts.NoCycle {
1678+
case NoCycleBehavior:
16781679
b.WriteString(" NOCYCLE")
16791680
}
16801681
if opts.RestartWith != nil {

pkg/sql/parser/mariadb.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -199,19 +199,19 @@ func (p *Parser) parseSequenceOptions() (ast.SequenceOptions, error) {
199199
case "MAXVALUE":
200200
opts.MaxValue = nil
201201
case "CYCLE":
202-
opts.NoCycle = true
202+
opts.CycleMode = ast.NoCycleBehavior
203203
case "CACHE":
204204
opts.Cache = nil
205205
opts.NoCache = true
206206
default:
207-
return opts, fmt.Errorf("unexpected token after NO in SEQUENCE options: %s", sub)
207+
return opts, p.expectedError("MINVALUE, MAXVALUE, CYCLE, or CACHE after NO")
208208
}
209209
case "CYCLE":
210210
p.advance()
211-
opts.Cycle = true
211+
opts.CycleMode = ast.CycleBehavior
212212
case "NOCYCLE":
213213
p.advance()
214-
opts.NoCycle = true
214+
opts.CycleMode = ast.NoCycleBehavior
215215
case "CACHE":
216216
p.advance()
217217
lit, err := p.parseNumericLit()
@@ -238,6 +238,10 @@ func (p *Parser) parseSequenceOptions() (ast.SequenceOptions, error) {
238238
return opts, nil
239239
}
240240
}
241+
// Validate: CACHE n and NOCACHE are mutually exclusive.
242+
if opts.Cache != nil && opts.NoCache {
243+
return opts, fmt.Errorf("contradictory sequence options: CACHE and NOCACHE cannot both be specified")
244+
}
241245
return opts, nil
242246
}
243247

pkg/sql/parser/mariadb_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ func TestMariaDB_CreateSequence_AllOptions(t *testing.T) {
4040
t.Fatalf("unexpected error: %v", err)
4141
}
4242
stmt := tree.Statements[0].(*ast.CreateSequenceStatement)
43-
if !stmt.Options.Cycle {
44-
t.Error("expected Cycle = true")
43+
if stmt.Options.CycleMode != ast.CycleBehavior {
44+
t.Error("expected CycleMode = CycleBehavior")
4545
}
4646
if stmt.Options.Cache == nil {
4747
t.Error("expected Cache to be set")

0 commit comments

Comments
 (0)