/
replacements.go
108 lines (93 loc) · 3.18 KB
/
replacements.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
106
107
108
package bqt
import (
"fmt"
"io/ioutil"
"regexp"
"strings"
)
/*
Given a SQL query and a replacement Struct, it applies the recplament on the SQL and returns a new SQL query. References to a Table are replaced
*/
func Replace(sql string, replacement Replacement) string {
if (replacement == Replacement{}) {
return sql
}
regexWithAlias, err := regexp.Compile(fmt.Sprintf(`(?i)%s\sas\s([A-z0-9_]+)\s`, replacement.TableFullName))
if err != nil {
panic(err)
}
useExistingAlias := fmt.Sprintf("(%s) AS $1 ", replacement.ReplaceSql)
newSql := regexWithAlias.ReplaceAllString(sql, useExistingAlias)
createAlias := fmt.Sprintf("(%s) AS %s", replacement.ReplaceSql, replacement.TableShortName)
newSql = strings.ReplaceAll(newSql, fmt.Sprintf("%s", replacement.TableFullName), createAlias)
return newSql
}
/*
Given the SQL code of a model and an Expected Output mock,
This function returns a SQL query which asserts that the output table of SQL is equal to the data contained in the mock
*/
func queryMinusMock(sql string, m Mock) (string, error) {
mockedSql, err := mockToSql(m)
if err != nil {
return "", err
}
columns := strings.Join(mockedSql.Columns, ",")
return fmt.Sprintf("SELECT %s FROM( %s ) \n EXCEPT DISTINCT \n SELECT %s FROM (%s)", columns, sql, columns, mockedSql.Sql), nil
}
func tableShortName(tableFullName string) string {
parts := strings.Split(tableFullName, ".") // Split the string by dot
lastItem := parts[len(parts)-1] // Get the last item
return lastItem
}
func sql(sqlToTest string, mocks map[string]Mock) (string, error) {
for tablefullName, mock := range mocks {
mockSql, err := mockToSql(mock)
if err != nil {
return "", err
}
tableShortName := tableShortName(tablefullName)
r := Replacement{ReplaceSql: mockSql.Sql,
TableFullName: tablefullName, TableShortName: tableShortName}
sqlToTest = Replace(sqlToTest, r)
}
return sqlToTest, nil
}
func mockMinusQuery(sql string, output Mock) (string, error) {
mockedSql, err := mockToSql(output)
if err != nil {
return "", err
}
columns := strings.Join(mockedSql.Columns, ",")
return fmt.Sprintf("SELECT %s FROM( %s ) \n EXCEPT DISTINCT \n SELECT %s FROM (%s)", columns, mockedSql.Sql, columns, sql), nil
}
type SQLTestQuery struct {
ExpectedMinusQuery string
QueryMinusExpected string
QueryWithMockedData string
}
func ReadContents(path string) (string, error) {
content, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
c := string(content)
return strings.TrimSpace(c), nil
}
/*
Given a Test it generates the SQL code that mocks data, run the needed logic and asserts the output data
*/
func GenerateTestSQL(t Test) (SQLTestQuery, error) {
queryWithMockedData, err := sql(t.FileContent, t.Mocks)
if err != nil {
return SQLTestQuery{}, err
}
sqlQueryMinusExpectation, err := queryMinusMock(queryWithMockedData, t.Output)
if err != nil {
return SQLTestQuery{}, err
}
sqlExpectationMinusQuery, err := mockMinusQuery(queryWithMockedData, t.Output)
if err != nil {
return SQLTestQuery{}, err
}
return SQLTestQuery{QueryMinusExpected: sqlQueryMinusExpectation, ExpectedMinusQuery: sqlExpectationMinusQuery, QueryWithMockedData: queryWithMockedData}, nil
}