-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
160 lines (135 loc) · 3.86 KB
/
main.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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package main
import (
"database/sql"
"fmt"
"log"
"os"
"regexp"
"strings"
"time"
"github.com/joho/godotenv"
_ "github.com/lib/pq"
"github.com/olekukonko/tablewriter"
)
// Connect to the database using the environment variables and return a pointer to the *sql.DB object
func connectDB() *sql.DB {
connStr := fmt.Sprintf("user=%s password=%s dbname=%s host=%s sslmode=%s",
os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"),
os.Getenv("DB_HOST"), os.Getenv("DB_SSLMODE"))
db, err := sql.Open("postgres", connStr)
if err != nil {
log.Fatal(err)
}
return db
}
// Execute the SQL query on the database and return the result rows and column names
func executeQuery(db *sql.DB, query string) (*sql.Rows, []string, error) {
rows, err := db.Query(query)
if err != nil {
return nil, nil, err
}
columns, err := rows.Columns()
if err != nil {
return nil, nil, err
}
return rows, columns, nil
}
// Print the result rows and column names in a table using the "tablewriter" package
func printResults(rows *sql.Rows, columns []string) {
data := [][]string{}
for rows.Next() {
var row []interface{}
for range columns {
var value interface{}
row = append(row, &value)
}
err := rows.Scan(row...)
if err != nil {
log.Fatal(err)
}
rowValues := []string{}
for _, value := range row {
if value == nil {
rowValues = append(rowValues, "NULL")
} else {
rowValues = append(rowValues, fmt.Sprintf("%v", value))
}
}
data = append(data, rowValues)
}
if err := rows.Err(); err != nil {
log.Fatal(err)
}
table := tablewriter.NewWriter(os.Stdout)
table.SetHeader(columns)
table.AppendBulk(data)
table.Render()
}
// Print the time taken to execute the SQL query
func printQueryTime(query string, duration time.Duration) {
fmt.Printf("Query: %s\nTime Taken: %f seconds\n\n", query, duration.Seconds())
}
// Print the total time taken to execute all SQL queries
func printTotalTime(totalTime time.Duration) {
fmt.Printf("Total Time Taken: %f seconds\n", totalTime.Seconds())
}
// Check if the SQL query is a command that does not produce output
func isSkipCommand(query string) bool {
// List of SQL commands that do not produce output
skipCommands := []string{
"CREATE", "ALTER", "INSERT", "DROP", "UPDATE", "DELETE",
"SET", "GRANT", "REVOKE", "COMMIT", "ROLLBACK",
}
for _, command := range skipCommands {
if strings.HasPrefix(strings.ToUpper(query), command) {
return true
}
}
return false
}
func main() {
// Load environment variables from .env file
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
// Connect to the database
db := connectDB()
defer db.Close()
// Read SQL queries from a file
queryBytes, err := os.ReadFile("queries.sql")
if err != nil {
log.Fatal(err)
}
// Remove comments from the SQL file
re := regexp.MustCompile(`--.*$|/\*[\s\S]*?\*/`)
cleanQueryBytes := re.ReplaceAll(queryBytes, []byte(""))
// Split the SQL queries by semicolons
queries := strings.Split(string(cleanQueryBytes), ";")
// Execute each SQL query and print the results
totalTime := time.Duration(0)
for _, query := range queries {
trimmedQuery := strings.TrimSpace(query)
if trimmedQuery == "" {
continue
}
// Measure the time taken to execute the query
startTime := time.Now()
// Execute the SQL query and get the result rows and column names
rows, columns, err := executeQuery(db, trimmedQuery)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
// Print the result rows and column names if the query is not a command that does not produce output
if rows.Next() || isSkipCommand(trimmedQuery) {
printResults(rows, columns)
}
// Print the time taken to execute the query
duration := time.Since(startTime)
totalTime += duration
printQueryTime(trimmedQuery, duration)
}
// Print the total time taken to execute all queries
printTotalTime(totalTime)
}