Skip to content

Commit 8a966f3

Browse files
authored
Merge branch 'main' into feat/linter-expansion
2 parents b407e34 + 4d96d5c commit 8a966f3

File tree

8 files changed

+642
-6
lines changed

8 files changed

+642
-6
lines changed

pkg/formatter/render.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,16 @@ func FormatStatement(s ast.Statement, opts ast.FormatOptions) string {
154154
return renderTruncate(v, opts)
155155
case *ast.MergeStatement:
156156
return renderMerge(v, opts)
157+
case *ast.CreateSequenceStatement:
158+
return renderCreateSequence(v, opts)
159+
case *ast.AlterSequenceStatement:
160+
return renderAlterSequence(v, opts)
161+
case *ast.DropSequenceStatement:
162+
return renderDropSequence(v, opts)
163+
case *ast.ShowStatement:
164+
return renderShow(v, opts)
165+
case *ast.DescribeStatement:
166+
return renderDescribe(v, opts)
157167
default:
158168
// Fallback to SQL() for unrecognized statement types
159169
return stmtSQL(s)
@@ -228,6 +238,11 @@ func renderSelect(s *ast.SelectStatement, opts ast.FormatOptions) string {
228238
sb.WriteString(joinSQL(&j))
229239
}
230240

241+
if s.Sample != nil {
242+
sb.WriteString(f.clauseSep())
243+
sb.WriteString(sampleSQL(s.Sample, f))
244+
}
245+
231246
if s.Where != nil {
232247
sb.WriteString(f.clauseSep())
233248
sb.WriteString(f.kw("WHERE"))
@@ -1178,6 +1193,29 @@ func tableRefSQL(t *ast.TableReference) string {
11781193
return sb.String()
11791194
}
11801195

1196+
// sampleSQL renders a ClickHouse SAMPLE clause.
1197+
func sampleSQL(s *ast.SampleClause, f *nodeFormatter) string {
1198+
var sb strings.Builder
1199+
sb.WriteString(f.kw("SAMPLE"))
1200+
sb.WriteString(" ")
1201+
sb.WriteString(s.Value)
1202+
if s.Denominator != "" {
1203+
sb.WriteString("/")
1204+
sb.WriteString(s.Denominator)
1205+
}
1206+
if s.Offset != "" {
1207+
sb.WriteString(" ")
1208+
sb.WriteString(f.kw("OFFSET"))
1209+
sb.WriteString(" ")
1210+
sb.WriteString(s.Offset)
1211+
if s.OffsetDenominator != "" {
1212+
sb.WriteString("/")
1213+
sb.WriteString(s.OffsetDenominator)
1214+
}
1215+
}
1216+
return sb.String()
1217+
}
1218+
11811219
// joinSQL renders a JOIN clause.
11821220
func joinSQL(j *ast.JoinClause) string {
11831221
var sb strings.Builder

pkg/formatter/render_ddl.go

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
// Copyright 2026 GoSQLX Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// render_ddl.go - formatter render handlers for DDL statements that have
16+
// dedicated AST nodes but previously fell through to the stmtSQL() fallback.
17+
// Covered: CREATE/ALTER/DROP SEQUENCE, SHOW, DESCRIBE.
18+
19+
package formatter
20+
21+
import (
22+
"strings"
23+
24+
"github.com/ajitpratap0/GoSQLX/pkg/sql/ast"
25+
)
26+
27+
// renderCreateSequence renders a CREATE [OR REPLACE] SEQUENCE [IF NOT EXISTS] statement.
28+
func renderCreateSequence(s *ast.CreateSequenceStatement, opts ast.FormatOptions) string {
29+
f := newNodeFormatter(opts)
30+
sb := f.sb
31+
32+
sb.WriteString(f.kw("CREATE"))
33+
if s.OrReplace {
34+
sb.WriteString(" ")
35+
sb.WriteString(f.kw("OR REPLACE"))
36+
}
37+
sb.WriteString(" ")
38+
sb.WriteString(f.kw("SEQUENCE"))
39+
if s.IfNotExists {
40+
sb.WriteString(" ")
41+
sb.WriteString(f.kw("IF NOT EXISTS"))
42+
}
43+
if s.Name != nil && s.Name.Name != "" {
44+
sb.WriteString(" ")
45+
sb.WriteString(s.Name.Name)
46+
}
47+
writeSequenceOptionsFormatted(sb, s.Options, f)
48+
return sb.String()
49+
}
50+
51+
// renderAlterSequence renders an ALTER SEQUENCE [IF EXISTS] statement.
52+
func renderAlterSequence(s *ast.AlterSequenceStatement, opts ast.FormatOptions) string {
53+
f := newNodeFormatter(opts)
54+
sb := f.sb
55+
56+
sb.WriteString(f.kw("ALTER SEQUENCE"))
57+
if s.IfExists {
58+
sb.WriteString(" ")
59+
sb.WriteString(f.kw("IF EXISTS"))
60+
}
61+
if s.Name != nil && s.Name.Name != "" {
62+
sb.WriteString(" ")
63+
sb.WriteString(s.Name.Name)
64+
}
65+
writeSequenceOptionsFormatted(sb, s.Options, f)
66+
return sb.String()
67+
}
68+
69+
// renderDropSequence renders a DROP SEQUENCE [IF EXISTS] statement.
70+
func renderDropSequence(s *ast.DropSequenceStatement, opts ast.FormatOptions) string {
71+
f := newNodeFormatter(opts)
72+
sb := f.sb
73+
74+
sb.WriteString(f.kw("DROP SEQUENCE"))
75+
if s.IfExists {
76+
sb.WriteString(" ")
77+
sb.WriteString(f.kw("IF EXISTS"))
78+
}
79+
if s.Name != nil && s.Name.Name != "" {
80+
sb.WriteString(" ")
81+
sb.WriteString(s.Name.Name)
82+
}
83+
return sb.String()
84+
}
85+
86+
// renderShow renders a SHOW statement (e.g., SHOW TABLES, SHOW DATABASES, SHOW CREATE TABLE x).
87+
func renderShow(s *ast.ShowStatement, opts ast.FormatOptions) string {
88+
f := newNodeFormatter(opts)
89+
sb := f.sb
90+
91+
sb.WriteString(f.kw("SHOW"))
92+
if s.ShowType != "" {
93+
sb.WriteString(" ")
94+
sb.WriteString(f.kw(strings.ToUpper(s.ShowType)))
95+
}
96+
if s.ObjectName != "" {
97+
sb.WriteString(" ")
98+
sb.WriteString(s.ObjectName)
99+
}
100+
if s.From != "" {
101+
sb.WriteString(" ")
102+
sb.WriteString(f.kw("FROM"))
103+
sb.WriteString(" ")
104+
sb.WriteString(s.From)
105+
}
106+
return sb.String()
107+
}
108+
109+
// renderDescribe renders a DESCRIBE/DESC statement.
110+
func renderDescribe(s *ast.DescribeStatement, opts ast.FormatOptions) string {
111+
f := newNodeFormatter(opts)
112+
sb := f.sb
113+
114+
sb.WriteString(f.kw("DESCRIBE"))
115+
if s.TableName != "" {
116+
sb.WriteString(" ")
117+
sb.WriteString(s.TableName)
118+
}
119+
return sb.String()
120+
}
121+
122+
// writeSequenceOptionsFormatted appends formatted sequence options to the builder.
123+
// It mirrors the logic in ast/sql.go writeSequenceOptions but uses the nodeFormatter
124+
// for keyword casing.
125+
func writeSequenceOptionsFormatted(sb *strings.Builder, opts ast.SequenceOptions, f *nodeFormatter) {
126+
if opts.StartWith != nil {
127+
sb.WriteString(" ")
128+
sb.WriteString(f.kw("START WITH"))
129+
sb.WriteString(" ")
130+
sb.WriteString(opts.StartWith.TokenLiteral())
131+
}
132+
if opts.IncrementBy != nil {
133+
sb.WriteString(" ")
134+
sb.WriteString(f.kw("INCREMENT BY"))
135+
sb.WriteString(" ")
136+
sb.WriteString(opts.IncrementBy.TokenLiteral())
137+
}
138+
if opts.MinValue != nil {
139+
sb.WriteString(" ")
140+
sb.WriteString(f.kw("MINVALUE"))
141+
sb.WriteString(" ")
142+
sb.WriteString(opts.MinValue.TokenLiteral())
143+
}
144+
if opts.MaxValue != nil {
145+
sb.WriteString(" ")
146+
sb.WriteString(f.kw("MAXVALUE"))
147+
sb.WriteString(" ")
148+
sb.WriteString(opts.MaxValue.TokenLiteral())
149+
}
150+
if opts.Cache != nil {
151+
sb.WriteString(" ")
152+
sb.WriteString(f.kw("CACHE"))
153+
sb.WriteString(" ")
154+
sb.WriteString(opts.Cache.TokenLiteral())
155+
} else if opts.NoCache {
156+
sb.WriteString(" ")
157+
sb.WriteString(f.kw("NOCACHE"))
158+
}
159+
switch opts.CycleMode {
160+
case ast.CycleBehavior:
161+
sb.WriteString(" ")
162+
sb.WriteString(f.kw("CYCLE"))
163+
case ast.NoCycleBehavior:
164+
sb.WriteString(" ")
165+
sb.WriteString(f.kw("NOCYCLE"))
166+
}
167+
if opts.RestartWith != nil {
168+
sb.WriteString(" ")
169+
sb.WriteString(f.kw("RESTART WITH"))
170+
sb.WriteString(" ")
171+
sb.WriteString(opts.RestartWith.TokenLiteral())
172+
} else if opts.Restart {
173+
sb.WriteString(" ")
174+
sb.WriteString(f.kw("RESTART"))
175+
}
176+
}

0 commit comments

Comments
 (0)