-
Notifications
You must be signed in to change notification settings - Fork 2
/
sql.go
105 lines (88 loc) · 2.73 KB
/
sql.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package sql
import (
"bytes"
"regexp"
"github.com/sergi/go-diff/diffmatchpatch"
"github.com/atlantistechnology/sdt/pkg/types"
"github.com/atlantistechnology/sdt/pkg/utils"
)
// colorDiff converts (DiffMatchPatch, []Diff) into colored text report
func colorDiff(
dmp *diffmatchpatch.DiffMatchPatch,
diffs []diffmatchpatch.Diff,
dumbterm bool,
minimal bool) string {
var buff bytes.Buffer
// Tool `sqlformat` doesn't normalize whitespace completely
reWhiteSpace := regexp.MustCompile(`^[\n\r\t ]+$`)
var highlights types.Highlights
if dumbterm {
highlights = types.Dumbterm
} else {
highlights = types.Colors
}
desc := highlights.Header +
"Comparison of canonicalized SQL (HEAD -> Current)\n" +
highlights.Neutral +
highlights.Clear
buff.WriteString(desc)
changed := false
for _, diff := range diffs {
text := diff.Text
switch diff.Type {
case diffmatchpatch.DiffInsert:
if !reWhiteSpace.MatchString(text) {
changed = true
}
buff.WriteString(highlights.Add)
buff.WriteString(text)
buff.WriteString(highlights.Clear)
case diffmatchpatch.DiffDelete:
if !reWhiteSpace.MatchString(text) {
changed = true
}
buff.WriteString(highlights.Del)
buff.WriteString(text)
buff.WriteString(highlights.Clear)
case diffmatchpatch.DiffEqual:
buff.WriteString(highlights.Neutral)
buff.WriteString(highlights.Clear)
buff.WriteString(text)
}
}
if changed {
return utils.BufferToDiff(buff, true, dumbterm, minimal)
}
return "| No semantic differences detected"
}
func Diff(filename string, options types.Options, config types.Config) string {
var currentCanonical []byte
var headCanonical []byte
sqlCmd := config.Commands["sql"].Executable
switches := config.Commands["sql"].Switches
canonical := true // Canonicalize rather than use parse tree
if filename == "" {
//-- Comparison of two local files
// Function name is slight misnomer since we use `canonical=true`
filename, headCanonical, currentCanonical = utils.LocalFileTrees(
sqlCmd, switches, options, "SQL", canonical)
} else {
//-- Comparison of a branch/revision to a current file
// Function name is slight misnomer since we use `canonical=true`
headCanonical, currentCanonical = utils.RevisionToCurrentTree(
filename, sqlCmd, switches, options, "SQL", canonical)
}
// Perform the diff between the versions
// Our canonicalizer isn't always consistent with trailing spaces
a := string(headCanonical)
b := string(currentCanonical)
dmp := diffmatchpatch.New()
diffs := dmp.DiffMain(a, b, false)
if options.Parsetree {
return "| SQL comparison uses canonicalization not AST analysis"
}
if options.Semantic {
return colorDiff(dmp, diffs, options.Dumbterm, options.Minimal)
}
return "| No diff type specified"
}