Skip to content

Commit 3a14336

Browse files
committed
Cleanup
1 parent 98f3a9e commit 3a14336

6 files changed

Lines changed: 95 additions & 176 deletions

File tree

go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ require (
3434
github.com/pmezard/go-difflib v1.0.0 // indirect
3535
github.com/shopspring/decimal v1.4.0 // indirect
3636
github.com/spf13/pflag v1.0.9 // indirect
37-
golang.org/x/crypto v0.43.0 // indirect
38-
golang.org/x/sync v0.17.0 // indirect
39-
golang.org/x/sys v0.37.0 // indirect
40-
golang.org/x/text v0.30.0 // indirect
37+
golang.org/x/crypto v0.46.0 // indirect
38+
golang.org/x/sync v0.19.0 // indirect
39+
golang.org/x/sys v0.39.0 // indirect
40+
golang.org/x/text v0.32.0 // indirect
4141
)

go.sum

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -78,19 +78,20 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
7878
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
7979
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
8080
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
81-
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
82-
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
83-
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
84-
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
85-
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
86-
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
81+
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
82+
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
83+
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
84+
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
85+
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
86+
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
87+
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
8788
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
8889
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
89-
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
90-
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
90+
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
91+
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
9192
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
92-
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
93-
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
93+
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
94+
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
9495
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
9596
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
9697
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=

sqlparser/mssql/document.go

Lines changed: 52 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -292,56 +292,63 @@ func (doc *TSqlDocument) parseDeclareBatch(s sqldocument.Scanner) (hasMore bool)
292292
// The isFirst parameter indicates whether this is the first batch in the file,
293293
// which affects whether DECLARE statements are allowed.
294294
func (doc *TSqlDocument) parseBatch(s sqldocument.Scanner, isFirst bool) (hasMore bool) {
295-
batch := &sqldocument.Batch{
296-
BatchSeparatorHandler: func(s sqldocument.Scanner, b *sqldocument.Batch) {
297-
errorEmitted := false
298-
for {
299-
switch s.NextToken() {
300-
case sqldocument.WhitespaceToken:
301-
continue
302-
case sqldocument.MalformedBatchSeparatorToken:
303-
if !errorEmitted {
304-
b.Errors = append(b.Errors, sqldocument.Error{
305-
Pos: s.Start(),
306-
Message: "`go` should be alone on a line without any comments",
307-
})
308-
errorEmitted = true
309-
}
310-
continue
311-
default:
312-
return
295+
batch := sqldocument.NewBatch()
296+
batch.BatchSeparatorHandler = func(s sqldocument.Scanner, b *sqldocument.Batch) {
297+
errorEmitted := false
298+
for {
299+
switch s.NextToken() {
300+
case sqldocument.WhitespaceToken:
301+
continue
302+
case sqldocument.MalformedBatchSeparatorToken:
303+
if !errorEmitted {
304+
b.Errors = append(b.Errors, sqldocument.Error{
305+
Pos: s.Start(),
306+
Message: "`go` should be alone on a line without any comments",
307+
})
308+
errorEmitted = true
313309
}
310+
continue
311+
default:
312+
return
313+
}
314+
}
315+
}
316+
batch.TokenHandlers = map[string]func(sqldocument.Scanner, *sqldocument.Batch) int{
317+
"declare": func(s sqldocument.Scanner, _ *sqldocument.Batch) int {
318+
// First declare-statement; enter a mode where we assume all contents
319+
// of batch are declare statements
320+
if !isFirst {
321+
doc.addError(s, "'declare' statement only allowed in first batch")
314322
}
323+
324+
// regardless of errors, go on and parse as far as we get...
325+
hasMore := doc.parseDeclareBatch(s)
326+
if hasMore {
327+
return 1
328+
}
329+
330+
return -1
315331
},
316-
TokenHandlers: map[string]func(sqldocument.Scanner, *sqldocument.Batch) bool{
317-
"declare": func(s sqldocument.Scanner, n *sqldocument.Batch) bool {
318-
// First declare-statement; enter a mode where we assume all contents
319-
// of batch are declare statements
320-
if !isFirst {
321-
doc.addError(s, "'declare' statement only allowed in first batch")
322-
}
332+
"create": func(s sqldocument.Scanner, b *sqldocument.Batch) int {
333+
counts, exists := b.TokenCalls["create"]
334+
if !exists {
335+
counts = 0
336+
}
323337

324-
// regardless of errors, go on and parse as far as we get...
325-
return doc.parseDeclareBatch(s)
326-
},
327-
"create": func(s sqldocument.Scanner, n *sqldocument.Batch) bool {
328-
// should be start of create procedure or create function...
329-
c := doc.parseCreate(s, n.CreateStatements)
330-
c.Driver = &mssql.Driver{}
331-
332-
// *prepend* what we saw before getting to the 'create'
333-
n.CreateStatements++
334-
c.Body = append(n.Nodes, c.Body...)
335-
c.Docstring = n.DocString
336-
doc.creates = append(doc.creates, c)
337-
338-
// fmt.Printf("%#v\n", s)
339-
// fmt.Printf("%#v\n", n)
340-
// fmt.Printf("%#v\n", doc)
341-
return true
342-
},
338+
// should be start of create procedure or create function...
339+
c := doc.parseCreate(s, counts)
340+
c.Driver = &mssql.Driver{}
341+
342+
// *prepend* what we saw before getting to the 'create'
343+
c.Body = append(b.Nodes, c.Body...)
344+
c.Docstring = b.DocString
345+
doc.creates = append(doc.creates, c)
346+
347+
//continue parsing
348+
return 0
343349
},
344350
}
351+
345352
hasMore = batch.Parse(s)
346353
if batch.HasErrors() {
347354
doc.errors = append(doc.errors, batch.Errors...)
@@ -397,6 +404,7 @@ func (d *TSqlDocument) parseCreate(s sqldocument.Scanner, createCountInBatch int
397404
sqldocument.RecoverToNextStatementCopying(s, &result.Body, TSQLStatementTokens)
398405
return
399406
}
407+
400408
var err error
401409
result.QuotedName, err = sqldocument.ParseCodeschemaName(s, &result.Body, TSQLStatementTokens)
402410
if err != nil {

sqlparser/mssql/document_test.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ create function [code].MyFunction ()
185185
create type [code].MyType ()
186186
create procedure [code].MyProcedure ()
187187
`)
188+
188189
// First function and last procedure triggers errors.
189190
assert.Len(t, doc.Errors(), 2)
190191
emsg := "a procedure/function must be alone in a batch; use 'go' to split batches"
@@ -199,8 +200,6 @@ func TestCreateProcs2(t *testing.T) {
199200
create type [code].MyType ()
200201
create procedure [code].FirstProc as table (x int)
201202
`)
202-
//repr.Println(doc.Errors())
203-
204203
// Code above was mainly to be able to step through parser in a given way.
205204
// First function triggers an error. Then create type is parsed which is
206205
// fine sharing a batch with others.
@@ -219,9 +218,8 @@ end
219218
// Code above was mainly to be able to step through parser in a given way.
220219
// First function triggers an error. Then create type is parsed which is
221220
// fine sharing a batch with others.
222-
require.Equal(t, 2, len(doc.Errors()))
221+
require.Equal(t, 1, len(doc.Errors()))
223222
assert.Equal(t, "`go` should be alone on a line without any comments", doc.Errors()[0].Message)
224-
assert.Equal(t, "Expected 'declare' or 'create', got: end", doc.Errors()[1].Message)
225223
}
226224

227225
func TestCreateAnnotationHappyDay(t *testing.T) {

sqlparser/mssql/scanner_test.go

Lines changed: 0 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -376,90 +376,6 @@ func TestScanner_Comments(t *testing.T) {
376376
}
377377
}
378378

379-
func TestScanner_BatchSeparator(t *testing.T) {
380-
tests := []struct {
381-
name string
382-
input string
383-
expected []sqldocument.TokenType
384-
}{
385-
{
386-
name: "go at start of file",
387-
input: "go",
388-
expected: []sqldocument.TokenType{
389-
sqldocument.BatchSeparatorToken,
390-
sqldocument.EOFToken,
391-
},
392-
},
393-
{
394-
name: "GO uppercase at start",
395-
input: "GO",
396-
expected: []sqldocument.TokenType{
397-
sqldocument.BatchSeparatorToken,
398-
sqldocument.EOFToken,
399-
},
400-
},
401-
{
402-
name: "go after newline",
403-
input: "SELECT 1\ngo",
404-
expected: []sqldocument.TokenType{
405-
sqldocument.ReservedWordToken, // SELECT
406-
sqldocument.WhitespaceToken,
407-
sqldocument.NumberToken, // 1
408-
sqldocument.WhitespaceToken,
409-
sqldocument.BatchSeparatorToken, // go
410-
sqldocument.EOFToken,
411-
},
412-
},
413-
{
414-
name: "go with trailing whitespace",
415-
input: "go \nSELECT",
416-
expected: []sqldocument.TokenType{
417-
sqldocument.BatchSeparatorToken,
418-
sqldocument.WhitespaceToken,
419-
sqldocument.ReservedWordToken,
420-
sqldocument.EOFToken,
421-
},
422-
},
423-
{
424-
name: "go mid-line is identifier",
425-
input: "SELECT go FROM",
426-
expected: []sqldocument.TokenType{
427-
sqldocument.ReservedWordToken, // SELECT
428-
sqldocument.WhitespaceToken,
429-
sqldocument.UnquotedIdentifierToken, // go (not batch separator)
430-
sqldocument.WhitespaceToken,
431-
sqldocument.ReservedWordToken, // FROM
432-
sqldocument.EOFToken,
433-
},
434-
},
435-
{
436-
name: "go with comment after is malformed",
437-
input: "go -- comment",
438-
expected: []sqldocument.TokenType{
439-
sqldocument.BatchSeparatorToken,
440-
sqldocument.WhitespaceToken,
441-
sqldocument.MalformedBatchSeparatorToken, // -- comment
442-
sqldocument.EOFToken,
443-
},
444-
},
445-
}
446-
447-
for _, tt := range tests {
448-
t.Run(tt.name, func(t *testing.T) {
449-
tokens := collectTokens(tt.input)
450-
if len(tokens) != len(tt.expected) {
451-
t.Fatalf("expected %d tokens, got %d: %+v", len(tt.expected), len(tokens), tokens)
452-
}
453-
for i, exp := range tt.expected {
454-
if tokens[i].Type != exp {
455-
t.Errorf("token %d: expected type %v, got %v (value: %q)",
456-
i, exp, tokens[i].Type, tokens[i].Value)
457-
}
458-
}
459-
})
460-
}
461-
}
462-
463379
func TestScanner_Position(t *testing.T) {
464380
input := "SELECT\n @var\n FROM"
465381
s := NewScanner("test.sql", input)
@@ -521,29 +437,6 @@ END`
521437
}
522438
}
523439

524-
func TestScanner_ToCommonToken(t *testing.T) {
525-
tests := []struct {
526-
tsqlToken sqldocument.TokenType
527-
commonToken sqldocument.TokenType
528-
}{
529-
{VarcharLiteralToken, sqldocument.StringLiteralToken},
530-
{NVarcharLiteralToken, sqldocument.StringLiteralToken},
531-
{BracketQuotedIdentifierToken, sqldocument.QuotedIdentifierToken},
532-
{UnterminatedVarcharLiteralErrorToken, sqldocument.UnterminatedStringErrorToken},
533-
{UnterminatedQuotedIdentifierErrorToken, sqldocument.UnterminatedStringErrorToken},
534-
{sqldocument.NumberToken, sqldocument.NumberToken}, // passthrough
535-
{sqldocument.WhitespaceToken, sqldocument.WhitespaceToken}, // passthrough
536-
}
537-
538-
for _, tt := range tests {
539-
result := ToCommonToken(tt.tsqlToken)
540-
if result != tt.commonToken {
541-
t.Errorf("ToCommonToken(%v): expected %v, got %v",
542-
tt.tsqlToken, tt.commonToken, result)
543-
}
544-
}
545-
}
546-
547440
func TestScanner_Clone(t *testing.T) {
548441
input := "SELECT FROM WHERE"
549442
s := NewScanner("test.sql", input)

sqlparser/sqldocument/batch.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,21 @@ type Batch struct {
2727
// Reset when non-comment, non-whitespace tokens are encountered.
2828
DocString []PosString
2929

30-
// CreateStatements tracks how many CREATE statements have been
31-
// processed in this batch. Can be used to enforce the validation rules
30+
// TokenCalls tracks how many Token handlers have been
31+
// called in this batch. Can be used to enforce the validation rules
3232
// that procedures and functions must be alone in their batch.
33-
CreateStatements int
33+
TokenCalls map[string]int
3434

3535
// TokenHandlers maps reserved words to their processing functions.
3636
// When a ReservedWordToken is encountered, its lowercase form is
3737
// looked up here. If found, the handler is called with the scanner
38-
// and batch. The handler returns true if parsing should continue
38+
// and batch.
39+
// The handler returns 1 if parsing should continue
3940
// with a new batch (e.g., after processing a batch separator).
40-
TokenHandlers map[string]func(Scanner, *Batch) bool
41+
// 1 = break and parse a new batch
42+
// 0 = continue (no return)
43+
// -1 = return false (stop parsing)
44+
TokenHandlers map[string]func(Scanner, *Batch) int
4145

4246
// Errors accumulates parsing errors encountered during batch processing.
4347
// Errors are collected rather than stopping parsing immediately,
@@ -48,6 +52,15 @@ type Batch struct {
4852
BatchSeparatorHandler func(Scanner, *Batch)
4953
}
5054

55+
func NewBatch() *Batch {
56+
return &Batch{
57+
TokenCalls: make(map[string]int, 0),
58+
Nodes: make([]Unparsed, 0),
59+
DocString: make([]PosString, 0),
60+
Errors: make([]Error, 0),
61+
}
62+
}
63+
5164
func (n *Batch) Create(s Scanner) {
5265
n.Nodes = append(n.Nodes, CreateUnparsed(s))
5366
}
@@ -89,8 +102,14 @@ func (n *Batch) Parse(s Scanner) bool {
89102
// Invoke the handler for this reserved word
90103
// The handler is responsible for advancing the scanner
91104
// and updating the batch as needed.
92-
// If handler returns true, we continue parsing a new batch.
93-
return handler(s, n)
105+
rt := handler(s, n)
106+
n.TokenCalls[token] += 1
107+
if rt == 1 {
108+
return true
109+
}
110+
if rt == -1 {
111+
return false
112+
}
94113
} else {
95114
s.NextToken()
96115
}

0 commit comments

Comments
 (0)